diff --git a/c-syncedit.cc b/c-syncedit.cc
index 3b80fbd..2e3ed23 100644
--- a/c-syncedit.cc
+++ b/c-syncedit.cc
@@ -410,64 +410,100 @@ void SyncEditor::SetSegmentTypes(
 /*----------------------------------------------------------------------------*/
 
 void SyncEditor::InsertPoint(
-		T_String const& id ,
+		T_SyncTrackId const& id ,
 		const uint32_t segmentIndex ,
 		const uint32_t pointIndex ) noexcept
 {
 	auto& sync{ Common::Sync( ) };
-	auto const* const curve{ sync.getCurve( id ) };
-	if ( !curve || segmentIndex >= curve->segments.size( ) ) {
-		return;
-	}
-	auto const& segment{ curve->segments[ segmentIndex ] };
-	if ( pointIndex == 0 || pointIndex > segment.values.size( )
-			|| segment.durations[ pointIndex - 1 ] == 1 ) {
+	auto const* const ovr{ id.isOverride ? sync.getOverride( id.id ) : nullptr };
+	if ( id.isOverride && !ovr ) {
 		return;
 	}
 
-	auto c{ *curve };
-	auto& ns{ c.segments[ segmentIndex ] };
+	const auto nc{ ovr ? ovr->inputNames( ).size( ) : 1 };
+	T_SyncCurve const* curves[ nc ];
+	if ( ovr ) {
+		for ( auto i = 0u ; i < nc ; i ++ ) {
+			curves[ i ] = sync.getCurve( ovr->inputNames( )[ i ] );
+		}
+	} else {
+		curves[ 0 ] = sync.getCurve( id.id );
+	}
 
-	const auto hd{ ns.durations[ pointIndex - 1 ] / 2 };
-	const float hv{ ns.computeValue( ns.findTimeOfPoint( pointIndex - 1 ) + hd ) };
-
-	ns.durations[ pointIndex - 1 ] -= hd;
-	ns.durations.insert( pointIndex - 1 , hd );
-	ns.values.insert( pointIndex , hv );
+	for ( auto const* curve : curves ) {
+		if ( !curve || segmentIndex >= curve->segments.size( ) ) {
+			return;
+		}
+		auto const& segment{ curve->segments[ segmentIndex ] };
+		if ( pointIndex == 0 || pointIndex > segment.values.size( )
+				|| segment.durations[ pointIndex - 1 ] == 1 ) {
+			return;
+		}
+	}
 
 	auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
 			Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
-	undo.curveReplacement( *curve , c );
-	sync.setCurve( std::move( c ) );
+
+	for ( auto const* curve : curves ) {
+		auto c{ *curve };
+		auto& ns{ c.segments[ segmentIndex ] };
+
+		const auto hd{ ns.durations[ pointIndex - 1 ] / 2 };
+		const float hv{ ns.computeValue( ns.findTimeOfPoint( pointIndex - 1 ) + hd ) };
+
+		ns.durations[ pointIndex - 1 ] -= hd;
+		ns.durations.insert( pointIndex - 1 , hd );
+		ns.values.insert( pointIndex , hv );
+		undo.curveReplacement( *curve , c );
+		sync.setCurve( std::move( c ) );
+	}
 }
 
 /*----------------------------------------------------------------------------*/
 
 void SyncEditor::DeletePoint(
-		T_String const& id ,
+		T_SyncTrackId const& id ,
 		const uint32_t segmentIndex ,
 		const uint32_t pointIndex ) noexcept
 {
 	auto& sync{ Common::Sync( ) };
-	auto const* const curve{ sync.getCurve( id ) };
-	if ( !curve || segmentIndex >= curve->segments.size( ) ) {
-		return;
-	}
-	auto const& segment{ curve->segments[ segmentIndex ] };
-	if ( pointIndex == 0 || pointIndex >= segment.values.size( ) ) {
+	auto const* const ovr{ id.isOverride ? sync.getOverride( id.id ) : nullptr };
+	if ( id.isOverride && !ovr ) {
 		return;
 	}
 
-	auto c{ *curve };
-	auto& ns{ c.segments[ segmentIndex ] };
-	ns.durations[ pointIndex ] += ns.durations[ pointIndex - 1 ];
-	ns.durations.remove( pointIndex - 1 );
-	ns.values.remove( pointIndex );
+	const auto nc{ ovr ? ovr->inputNames( ).size( ) : 1 };
+	T_SyncCurve const* curves[ nc ];
+	if ( ovr ) {
+		for ( auto i = 0u ; i < nc ; i ++ ) {
+			curves[ i ] = sync.getCurve( ovr->inputNames( )[ i ] );
+		}
+	} else {
+		curves[ 0 ] = sync.getCurve( id.id );
+	}
+
+	for ( auto const* curve : curves ) {
+		if ( !curve || segmentIndex >= curve->segments.size( ) ) {
+			return;
+		}
+		auto const& segment{ curve->segments[ segmentIndex ] };
+		if ( pointIndex == 0 || pointIndex >= segment.values.size( ) ) {
+			return;
+		}
+	}
 
 	auto& undo{ dynamic_cast< T_UndoSyncChanges& >(
 			Common::Undo( ).add< T_UndoSyncChanges >( ) ) };
-	undo.curveReplacement( *curve , c );
-	sync.setCurve( std::move( c ) );
+	for ( auto const* curve : curves ) {
+		auto c{ *curve };
+		auto& ns{ c.segments[ segmentIndex ] };
+		ns.durations[ pointIndex ] += ns.durations[ pointIndex - 1 ];
+		ns.durations.remove( pointIndex - 1 );
+		ns.values.remove( pointIndex );
+
+		undo.curveReplacement( *curve , c );
+		sync.setCurve( std::move( c ) );
+	}
 }
 
 /*----------------------------------------------------------------------------*/
diff --git a/c-syncedit.hh b/c-syncedit.hh
index 9e6427c..c4cd825 100644
--- a/c-syncedit.hh
+++ b/c-syncedit.hh
@@ -154,14 +154,14 @@ struct SyncEditor final
 	// Insert a point in a segment. The pointIndex parameter indicates the
 	// index of the new point; it must not be 0 or nbPoints( segment )
 	static void InsertPoint(
-			T_String const& id ,
+			T_SyncTrackId const& id ,
 			uint32_t segmentIndex ,
 			uint32_t pointIndex ) noexcept;
 
 	// Delete a point from a segment. The point must not be the first or last
 	// point in the segment.
 	static void DeletePoint(
-			T_String const& id ,
+			T_SyncTrackId const& id ,
 			uint32_t segmentIndex ,
 			uint32_t pointIndex ) noexcept;
 
diff --git a/ui-sequencer.cc b/ui-sequencer.cc
index e5ee7be..f9a1de4 100644
--- a/ui-sequencer.cc
+++ b/ui-sequencer.cc
@@ -743,11 +743,15 @@ void T_SyncViewImpl_::sequencerWidget( ) noexcept
 			selSegment = dSeg.seg;
 			selPoint = dPoint.index;
 			selPointDnD = io.MouseDown[ 0 ] && dPoint.index != 0;
-			if ( selPointDnD ) {
+			if ( selPointDnD && !selId->isOverride ) { // XXX
 				assert( selUpdate == E_ChangeType::NONE );
 				selPointDnDStart = selPointDnDCur = mPixels;
-				selUpdatingOriginal = *sync.getCurve( selId->id ); // XXX
+				selUpdatingOriginal = *sync.getCurve( selId->id );
 				selUpdate = E_ChangeType::POINT_DND;
+			} else if ( selId->isOverride ) {
+				printf( "FIXME!\n" );
+				selPointDnD = false;
+#warning blah
 			}
 			sub = E_SubWindow::SW_POINT;
 		}
@@ -1255,7 +1259,7 @@ T_SyncViewImpl_::T_MousePos T_SyncViewImpl_::getMousePos( ) const noexcept
 			}
 			for ( auto k = 0u ; k < seg.dispPoints ; k ++ ) {
 				auto const& p{ dspPoints[ seg.firstPoint + k ] };
-				if ( ImLengthSqr( mp - p.center ) <= PointRadiusSqr ) {
+				if ( ImLengthSqr( mp - p.center ) <= PointRadiusSqr * 2.25 ) {
 					return T_MousePos{ E_MousePosType::POINT ,
 						seg.firstPoint + k };
 				}
@@ -1844,14 +1848,23 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept
 	const uint32_t sid{ *selSegment };
 	const uint32_t pid{ *selPoint };
 	auto& sync{ Common::Sync( ) };
+	auto const* const ovr{ selId->isOverride
+		? sync.getOverride( selId->id )
+		: nullptr };
 	auto const* const curve{ selUpdatingCopy
 		? selUpdatingCopy.target( )
-		: sync.getCurve( selId->id ) };
+		: sync.getCurve( ovr ? ovr->inputNames( )[ 0 ] : selId->id ) };
 	auto const& segment{ curve->segments[ sid ] };
 
-	Text( "Curve:" );
-	SameLine( 110 );
-	Text( "%s" , selId->id.toOSString( ).data( ) );
+	if ( selId->isOverride ) {
+		Text( "Override:" );
+		SameLine( 110 );
+		Text( "%s" , ovr->title( ) );
+	} else {
+		Text( "Curve:" );
+		SameLine( 110 );
+		Text( "%s" , selId->id.toOSString( ).data( ) );
+	}
 
 	Text( "Segment index:" );
 	SameLine( 110 );
@@ -1895,13 +1908,19 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept
 
 	Separator( );
 
-	Text( "Value:" );
-	SameLine( 110 );
+	bool changed;
 	float value{ segment.values[ pid ] };
-	PushItemWidth( -1 );
-	DragFloat( "##value" , &value , .01f , 0 , 0 , "%.6f" );
-	const bool changed{ IsItemActive( ) };
-	PopItemWidth( );
+	if ( ovr ) {
+		// XXX override control
+		changed = false;
+	} else {
+		Text( "Value:" );
+		SameLine( 110 );
+		PushItemWidth( -1 );
+		DragFloat( "##value" , &value , .01f , 0 , 0 , "%.6f" );
+		changed = IsItemActive( );
+		PopItemWidth( );
+	}
 
 	const bool canUseButtons{ !changed && selUpdate == E_ChangeType::NONE };
 	const auto canInsertBefore{ pid != 0
@@ -1913,7 +1932,7 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept
 		Text( " " );
 		SameLine( 110 );
 		if ( Button( "Delete point" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
-			SyncEditor::DeletePoint( selId->id , sid , pid );
+			SyncEditor::DeletePoint( *selId , sid , pid );
 			selPoint.clear( );
 			sub = SW_SEGMENT;
 		}
@@ -1925,7 +1944,7 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept
 			Text( " " );
 			SameLine( 110 );
 			if ( Button( "Insert before" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
-				SyncEditor::InsertPoint( selId->id , sid , pid );
+				SyncEditor::InsertPoint( *selId , sid , pid );
 				(*selPoint) ++;
 			}
 		}
@@ -1933,7 +1952,7 @@ void T_SyncViewImpl_::displayPointWindow( ) noexcept
 			Text( " " );
 			SameLine( 110 );
 			if ( Button( "Insert after" , ImVec2{ -1 , 0 } ) && canUseButtons ) {
-				SyncEditor::InsertPoint( selId->id , sid , pid + 1 );
+				SyncEditor::InsertPoint( *selId , sid , pid + 1 );
 			}
 		}
 	}