commit 019a90dbe28d0be8ad94ad8ab44734151744c89a
Author: Colin Fletcher <colin.m.fletcher@googlemail.com>
Date:   Thu Sep 13 16:05:23 2018 +0100

    Implement new 'Enclosed' region equivalence mode.
    
    Now applies to master

diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index e086363a2..8cca0227f 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -2138,7 +2138,6 @@ RCOptionEditor::RCOptionEditor ()
 
 	uint32_t hwcpus = hardware_concurrency ();
 	BoolOption* bo;
-	BoolComboOption* bco;
 
 	if (hwcpus > 1) {
 		add_option (_("General"), new OptionEditorHeading (_("DSP CPU Utilization")));
@@ -2444,16 +2443,18 @@ RCOptionEditor::RCOptionEditor ()
 
 	add_option (_("Editor"), fadeshape);
 
-	bco = new BoolComboOption (
-		     "use-overlap-equivalency",
-		     _("Regions in edit groups are edited together"),
-		     _("whenever they overlap in time"),
-		     _("only if they have identical length and position"),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
-		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
+	ComboOption<RegionEquivalence> *eqv = new ComboOption<RegionEquivalence> (
+		     "region-equivalence",
+		     _("Regions in active edit groups are edited together"),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_equivalence),
+		     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_equivalence)
 		     );
 
-	add_option (_("Editor"), bco);
+	eqv->add (Overlap, _("whenever they overlap in time"));
+	eqv->add (Enclosed, _("if either encloses the other"));
+	eqv->add (Exact, _("only if they have identical length, position and origin"));
+
+	add_option (_("Editor"), eqv);
 
 	ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
 		"layer-model",
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 681c51a32..b7ee95e9e 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -212,7 +212,7 @@ CONFIG_VARIABLE (bool, verify_remove_last_capture, "verify-remove-last-capture",
 CONFIG_VARIABLE (bool, save_history, "save-history", true)
 CONFIG_VARIABLE (int32_t, saved_history_depth, "save-history-depth", 20)
 CONFIG_VARIABLE (int32_t, history_depth, "history-depth", 20)
-CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false)
+CONFIG_VARIABLE (RegionEquivalence, region_equivalence, "region-equivalence", Enclosed)
 CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
 CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
 CONFIG_VARIABLE (float, automation_interval_msecs, "automation-interval-msecs", 30)
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index b536aa16a..5d0413beb 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -201,9 +201,10 @@ public:
 		return Evoral::coverage (first_sample(), last_sample(), start, end);
 	}
 
-	bool equivalent (boost::shared_ptr<const Region>) const;
+	bool exact_equivalent (boost::shared_ptr<const Region>) const;
 	bool size_equivalent (boost::shared_ptr<const Region>) const;
 	bool overlap_equivalent (boost::shared_ptr<const Region>) const;
+	bool enclosed_equivalent (boost::shared_ptr<const Region>) const;
 	bool region_list_equivalent (boost::shared_ptr<const Region>) const;
 	bool source_equivalent (boost::shared_ptr<const Region>) const;
 	bool any_source_equivalent (boost::shared_ptr<const Region>) const;
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index f835a5ff0..366e30318 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -605,6 +605,12 @@ namespace ARDOUR {
 	class Bundle;
 	typedef std::vector<boost::shared_ptr<Bundle> > BundleList;
 
+	enum RegionEquivalence {
+		Exact,
+		Enclosed,
+		Overlap
+	};
+
 	enum WaveformScale {
 		Linear,
 		Logarithmic
diff --git a/libs/ardour/ardour/types_convert.h b/libs/ardour/ardour/types_convert.h
index 831761498..dcdc49fae 100644
--- a/libs/ardour/ardour/types_convert.h
+++ b/libs/ardour/ardour/types_convert.h
@@ -68,6 +68,7 @@ DEFINE_ENUM_CONVERT(ARDOUR::PluginType)
 DEFINE_ENUM_CONVERT(ARDOUR::AlignStyle)
 DEFINE_ENUM_CONVERT(ARDOUR::AlignChoice)
 
+DEFINE_ENUM_CONVERT(ARDOUR::RegionEquivalence)
 DEFINE_ENUM_CONVERT(ARDOUR::WaveformScale)
 DEFINE_ENUM_CONVERT(ARDOUR::WaveformShape)
 DEFINE_ENUM_CONVERT(ARDOUR::VUMeterStandard)
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 74e445a37..1173a99b0 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -127,6 +127,7 @@ setup_enum_writer ()
 	MidiModel::NoteDiffCommand::Property _MidiModel_NoteDiffCommand_Property;
 	MidiModel::SysExDiffCommand::Property _MidiModel_SysExDiffCommand_Property;
 	MidiModel::PatchChangeDiffCommand::Property _MidiModel_PatchChangeDiffCommand_Property;
+	RegionEquivalence _RegionEquivalence;
 	WaveformScale _WaveformScale;
 	WaveformShape _WaveformShape;
 	Session::PostTransportWork _Session_PostTransportWork;
@@ -685,6 +686,11 @@ setup_enum_writer ()
 	REGISTER_ENUM(MidiPortSelection);
 	REGISTER_BITS(_MidiPortFlags);
 
+	REGISTER_ENUM(Exact);
+	REGISTER_ENUM(Enclosed);
+	REGISTER_ENUM(Overlap);
+	REGISTER(_RegionEquivalence);
+
 	REGISTER_ENUM(Linear);
 	REGISTER_ENUM(Logarithmic);
 	REGISTER(_WaveformScale);
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index c3b91f3f4..c992c1057 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -839,18 +839,28 @@ Playlist::remove_region_internal (boost::shared_ptr<Region> region)
 void
 Playlist::get_equivalent_regions (boost::shared_ptr<Region> other, vector<boost::shared_ptr<Region> >& results)
 {
-	if (Config->get_use_overlap_equivalency()) {
-		for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-			if ((*i)->overlap_equivalent (other)) {
-				results.push_back (*i);
-			}
-		}
-	} else {
-		for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
-			if ((*i)->equivalent (other)) {
-				results.push_back (*i);
-			}
-		}
+	switch (Config->get_region_equivalence()) {
+		 case Exact:
+			 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+				 if ((*i)->exact_equivalent (other)) {
+					 results.push_back (*i);
+				 }
+			 }
+			 break;
+		 case Enclosed:
+			 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+				 if ((*i)->enclosed_equivalent (other)) {
+					 results.push_back (*i);
+				 }
+			 }
+			 break;
+		 case Overlap:
+			 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+				 if ((*i)->overlap_equivalent (other)) {
+					 results.push_back (*i);
+				 }
+			 }
+			 break;
 	}
 }
 
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index cad32cd4d..d4afb7d9c 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -1478,7 +1478,14 @@ Region::overlap_equivalent (boost::shared_ptr<const Region> other) const
 }
 
 bool
-Region::equivalent (boost::shared_ptr<const Region> other) const
+Region::enclosed_equivalent (boost::shared_ptr<const Region> other) const
+{
+	return (first_sample() >= other->first_sample() && last_sample() <= other->last_sample()) ||
+	       (first_sample() <= other->first_sample() && last_sample() >= other->last_sample()) ;
+}
+
+bool
+Region::exact_equivalent (boost::shared_ptr<const Region> other) const
 {
 	return _start == other->_start &&
 		_position == other->_position &&
