Index: /applications/editors/josm/plugins/dumbutils/src/dumbutils/AlignWayNodesAction.java
===================================================================
--- /applications/editors/josm/plugins/dumbutils/src/dumbutils/AlignWayNodesAction.java	(revision 25870)
+++ /applications/editors/josm/plugins/dumbutils/src/dumbutils/AlignWayNodesAction.java	(revision 25870)
@@ -0,0 +1,94 @@
+package dumbutils;
+
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.RelationData;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.*;
+import java.util.*;
+import java.awt.event.KeyEvent;
+import org.openstreetmap.josm.tools.Shortcut;
+import java.awt.event.ActionEvent;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+/**
+ * Pastes relation membership from objects in the paste buffer onto selected object(s).
+ *
+ * @author Zverik
+ */
+class AlignWayNodesAction extends JosmAction {
+    private static final String TITLE = "Align way nodes";
+
+    public AlignWayNodesAction() {
+        super(tr(TITLE), "alignwaynodes", tr("Align nodes in a way"), null, true);
+    }
+
+    public void actionPerformed( ActionEvent e ) {
+        Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
+        Set<Node> selectedNodes = filterNodes(selection);
+        Set<Way> ways = findCommonWays(selectedNodes);
+        if( ways == null || ways.size() != 1 )
+            return;
+        Way way = ways.iterator().next();
+
+        // Prepare a list of nodes to align
+        List<Node> nodes = new ArrayList<Node>();
+        for( int i = 0; i < way.getNodesCount(); i++ ) {
+            Node node = way.getNode(i);
+            if( selectedNodes.contains(node) ) {
+                nodes.add(node);
+                selectedNodes.remove(node);
+            }
+            // todo: 1 node - add adjacent; 2 nodes - add all between them
+        }
+
+        List<Command> commands = new ArrayList<Command>();
+        if( !commands.isEmpty() )
+            Main.main.undoRedo.add(new SequenceCommand(tr(TITLE), commands));
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if( getCurrentDataSet() == null ) {
+            setEnabled(false);
+        }  else
+            updateEnabledState(getCurrentDataSet().getSelected());
+    }
+
+    @Override
+    protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
+        Set<Way> ways = findCommonWays(filterNodes(selection));
+        setEnabled(ways != null && ways.size() == 1);
+    }
+
+    private Set<Way> findCommonWays( Set<Node> nodes ) {
+        Set<Way> ways = null;
+        for( Node n : nodes ) {
+            List<Way> referrers = OsmPrimitive.getFilteredList(n.getReferrers(), Way.class);
+            if( ways == null )
+                ways = new HashSet<Way>(referrers);
+            else {
+                if( !ways.containsAll(referrers) )
+                    return null;
+                ways.retainAll(referrers);
+            }
+        }
+        return ways;
+    }
+
+    private Set<Node> filterNodes( Collection<? extends OsmPrimitive> selection ) {
+        Set<Node> result = new HashSet<Node>();
+        if( selection != null ) {
+            for( OsmPrimitive p : selection )
+                if( p instanceof Node )
+                    result.add((Node)p);
+        }
+        return result;
+    }
+}
Index: /applications/editors/josm/plugins/dumbutils/src/dumbutils/DumbUtilsPlugin.java
===================================================================
--- /applications/editors/josm/plugins/dumbutils/src/dumbutils/DumbUtilsPlugin.java	(revision 25869)
+++ /applications/editors/josm/plugins/dumbutils/src/dumbutils/DumbUtilsPlugin.java	(revision 25870)
@@ -12,4 +12,7 @@
     JMenuItem replaceGeometry;
     JMenuItem tagBuffer;
+    JMenuItem sourceTag;
+    JMenuItem pasteRelations;
+    JMenuItem alignWayNodes;
 
     public DumbUtilsPlugin(PluginInformation info) {
@@ -18,4 +21,7 @@
         replaceGeometry = MainMenu.add(Main.main.menu.toolsMenu, new ReplaceGeometryAction());
         tagBuffer = MainMenu.add(Main.main.menu.toolsMenu, new TagBufferAction());
+        sourceTag = MainMenu.add(Main.main.menu.toolsMenu, new TagSourceAction());
+        pasteRelations = MainMenu.add(Main.main.menu.toolsMenu, new PasteRelationsAction());
+//        alignWayNodes = MainMenu.add(Main.main.menu.toolsMenu, new AlignWayNodesAction());
     }
 
@@ -25,4 +31,7 @@
         replaceGeometry.setEnabled(enabled);
         tagBuffer.setEnabled(enabled);
+        sourceTag.setEnabled(enabled);
+        pasteRelations.setEnabled(enabled);
+//        alignWayNodes.setEnabled(enabled);
     }
 }
Index: /applications/editors/josm/plugins/dumbutils/src/dumbutils/PasteRelationsAction.java
===================================================================
--- /applications/editors/josm/plugins/dumbutils/src/dumbutils/PasteRelationsAction.java	(revision 25870)
+++ /applications/editors/josm/plugins/dumbutils/src/dumbutils/PasteRelationsAction.java	(revision 25870)
@@ -0,0 +1,86 @@
+package dumbutils;
+
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.RelationData;
+import org.openstreetmap.josm.data.osm.PrimitiveData;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.*;
+import java.util.*;
+import java.awt.event.KeyEvent;
+import org.openstreetmap.josm.tools.Shortcut;
+import java.awt.event.ActionEvent;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+/**
+ * Pastes relation membership from objects in the paste buffer onto selected object(s).
+ *
+ * @author Zverik
+ */
+class PasteRelationsAction extends JosmAction {
+    private static final String TITLE = "Paste relations";
+
+    public PasteRelationsAction() {
+        super(tr(TITLE), "pasterelations", tr("Paste relation membership from objects in the buffer onto selected object(s)"),
+                Shortcut.registerShortcut("tools:pasterelations", tr(TITLE), KeyEvent.VK_V, Shortcut.GROUP_MENU, Shortcut.SHIFT_DEFAULT), true);
+    }
+
+    public void actionPerformed( ActionEvent e ) {
+        Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
+        if( selection.isEmpty() )
+            return;
+
+        Map<Relation, String> relations = new HashMap<Relation, String>();
+        for( PrimitiveData pdata : Main.pasteBuffer.getDirectlyAdded() ) {
+            OsmPrimitive p = getCurrentDataSet().getPrimitiveById(pdata.getId(), pdata.getType());
+            for( Relation r : OsmPrimitive.getFilteredList(p.getReferrers(), Relation.class)) {
+                String role = relations.get(r);
+                for( RelationMember m : r.getMembers() ) {
+                    if( m.getMember().equals(p) ) {
+                        String newRole = m.getRole();
+                        if( newRole != null && role == null )
+                            role = newRole;
+                        else if( newRole != null ? !newRole.equals(role) : role != null ) {
+                            role = "";
+                            break;
+                        }
+                    }
+                }
+                relations.put(r, role);
+            }
+        }
+
+        List<Command> commands = new ArrayList<Command>();
+        for( Relation rel : relations.keySet() ) {
+            Relation r = new Relation(rel);
+            boolean changed = false;
+            for( OsmPrimitive p : selection ) {
+                if( !r.getMemberPrimitives().contains(p) ) {
+                    r.addMember(new RelationMember(relations.get(rel), p));
+                    changed = true;
+                }
+            }
+            if( changed )
+                commands.add(new ChangeCommand(rel, r));
+        }
+
+        if( !commands.isEmpty() )
+            Main.main.undoRedo.add(new SequenceCommand(tr(TITLE), commands));
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if( getCurrentDataSet() == null ) {
+            setEnabled(false);
+        }  else
+            updateEnabledState(getCurrentDataSet().getSelected());
+    }
+
+    @Override
+    protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
+        setEnabled(selection != null && !selection.isEmpty() );
+    }
+}
Index: /applications/editors/josm/plugins/dumbutils/src/dumbutils/ReplaceGeometryAction.java
===================================================================
--- /applications/editors/josm/plugins/dumbutils/src/dumbutils/ReplaceGeometryAction.java	(revision 25869)
+++ /applications/editors/josm/plugins/dumbutils/src/dumbutils/ReplaceGeometryAction.java	(revision 25870)
@@ -102,5 +102,8 @@
             commands.add(new ChangePropertyCommand(way, key, geometry.get(key)));
 
-        // And delete odl geometry way
+        // Remove geometry way from selection
+        getCurrentDataSet().clearSelection(geometry);
+
+        // And delete old geometry way
         commands.add(new DeleteCommand(geometry));
 
Index: /applications/editors/josm/plugins/dumbutils/src/dumbutils/TagSourceAction.java
===================================================================
--- /applications/editors/josm/plugins/dumbutils/src/dumbutils/TagSourceAction.java	(revision 25870)
+++ /applications/editors/josm/plugins/dumbutils/src/dumbutils/TagSourceAction.java	(revision 25870)
@@ -0,0 +1,83 @@
+package dumbutils;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.*;
+import java.util.*;
+import java.awt.event.KeyEvent;
+import org.openstreetmap.josm.tools.Shortcut;
+import java.awt.event.ActionEvent;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+/**
+ * Remembers last source value and put it on selected object(s).
+ *
+ * @author Zverik
+ */
+class TagSourceAction extends JosmAction {
+    private static final String TITLE = "Add source tag";
+    private String source;
+    private Set<OsmPrimitive> selectionBuf = new HashSet<OsmPrimitive>();
+    private boolean clickedTwice = false;
+
+    public TagSourceAction() {
+        super(tr(TITLE), "sourcetag", tr("Add remembered source tag"),
+                Shortcut.registerShortcut("tools:sourcetag", tr(TITLE), KeyEvent.VK_S, Shortcut.GROUP_MENU), true);
+        source = Main.pref.get("sourcetag.value");
+    }
+
+    public void actionPerformed( ActionEvent e ) {
+        Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
+        if( selection.isEmpty() || source == null || source.length() == 0 )
+            return;
+
+        Main.main.undoRedo.add(new ChangePropertyCommand(selection, "source", source));
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if( getCurrentDataSet() == null ) {
+            setEnabled(false);
+            if( selectionBuf != null )
+                selectionBuf.clear();
+        }  else
+            updateEnabledState(getCurrentDataSet().getSelected());
+    }
+
+    @Override
+    protected void updateEnabledState( Collection<? extends OsmPrimitive> selection ) {
+        if( selection == null || selection.isEmpty() ) {
+            selectionBuf.clear();
+            clickedTwice = false;
+            setEnabled(false);
+            return;
+        }
+
+        if( selectionBuf.size() == selection.size() && selectionBuf.containsAll(selection) ) {
+            if( !clickedTwice )
+                clickedTwice = true;
+            else {
+                // tags may have been changed, get the source
+                String newSource = null;
+                for( OsmPrimitive p : selection ) {
+                    String value = p.get("source");
+                    if( value != null && newSource == null )
+                        newSource = value;
+                    else if( value != null ? !value.equals(newSource) : newSource != null ) {
+                        newSource = "";
+                        break;
+                    }
+                }
+                if( newSource != null && newSource.length() > 0 && !newSource.equals(source) ) {
+                    source = newSource;
+                    Main.pref.put("sourcetag.value", source);
+                }
+            }
+        } else
+            clickedTwice = false;
+        selectionBuf.clear();
+        selectionBuf.addAll(selection);
+        setEnabled(source != null && source.length() > 0);
+    }
+}
Index: /applications/editors/josm/plugins/relcontext/TODO
===================================================================
--- /applications/editors/josm/plugins/relcontext/TODO	(revision 25869)
+++ /applications/editors/josm/plugins/relcontext/TODO	(revision 25870)
@@ -5,11 +5,4 @@
 - "Reverse multipolygon": create a closed area out of outer members, move tags, delete relation and empty ways
 - Fix tags for public_transport relations
-
-== DumbUtils todo ==
-
-- Paste relations to another object (Main.pasteBuffer.getDirectlyAdded() -> relations)
-- Align way nodes: 1 node - between neighboring, 2 nodes - all between them, 3 or more - all selected
-- Paste remembered source tag value (store it indefinetly, even in preferences)
-- Replace geometry: choose nearest node for replacing, not just any
 
 == NEW ALGORITHM ==
