Index: /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 4457)
+++ /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 4458)
@@ -334,21 +334,14 @@
         // TODO: Only display this warning when nodes outside dataSourceArea are deleted
         Area dataSourceArea = Main.main.getCurrentDataSet().getDataSourceArea();
-        if (dataSourceArea != null) {
-            for (Node node : allNodes) {
-                if (!dataSourceArea.contains(node.getCoor())) {
-                    int option = JOptionPane.showConfirmDialog(Main.parent,
-                            trn("The selected way has nodes outside of the downloaded data region.",
-                                    "The selected ways have nodes outside of the downloaded data region.",
-                                    ways.size()) + "\n"
-                                    + tr("This can lead to nodes being deleted accidentally.") + "\n"
-                                    + tr("Are you really sure to continue?"),
-                                    tr("Please abort if you are not sure"), JOptionPane.YES_NO_OPTION,
-                                    JOptionPane.WARNING_MESSAGE);
-
-                    if (option != JOptionPane.YES_OPTION) return;
-                    break;
-                }
-            }
-        }
+        boolean ok = Command.checkAndConfirmOutlyingOperation("joinarea", tr("Join area confirmation"),
+                trn("The selected way has nodes outside of the downloaded data region.",
+                    "The selected ways have nodes outside of the downloaded data region.",
+                    ways.size()) + "<br/>"
+                    + tr("This can lead to nodes being deleted accidentally.") + "<br/>"
+                    + tr("Are you really sure to continue?")
+                    + tr("Please abort if you are not sure"),
+                tr("The selected area is incomplete. Continue?"),
+                dataSourceArea, allNodes, null);
+        if(!ok) return;
 
         //analyze multipolygon relations and collect all areas
Index: /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 4457)
+++ /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 4458)
@@ -61,4 +61,5 @@
      * This method does some checking on the selection and calls the matching unGlueWay method.
      */
+    @Override
     public void actionPerformed(ActionEvent e) {
 
@@ -67,4 +68,7 @@
         String errMsg = null;
         if (checkSelection(selection)) {
+            if (!checkAndConfirmOutlyingUnglue()) {
+                return;
+            }
             int count = 0;
             for (Way w : OsmPrimitive.getFilteredList(selectedNode.getReferrers(), Way.class)) {
@@ -87,4 +91,7 @@
             }
         } else if (checkSelection2(selection)) {
+            if (!checkAndConfirmOutlyingUnglue()) {
+                return;
+            }
             ArrayList<Node> tmpNodes = new ArrayList<Node>();
             for (Node n : selectedNodes) {
@@ -408,3 +415,25 @@
         setEnabled(selection != null && !selection.isEmpty());
     }
+
+    protected boolean checkAndConfirmOutlyingUnglue() {
+        List<OsmPrimitive> primitives = new ArrayList<OsmPrimitive>(2 + (selectedNodes == null ? 0 : selectedNodes.size()));
+        if (selectedNodes != null)
+            primitives.addAll(selectedNodes);
+        if (selectedNode != null)
+            primitives.add(selectedNode);
+        if (selectedWay != null)
+            primitives.add(selectedWay);
+        return Command.checkAndConfirmOutlyingOperation("unglue",
+                tr("Unglue confirmation"),
+                tr("You are about to unglue nodes outside of the area you have downloaded."
+                        + "<br>"
+                        + "This can cause problems because other objects (that you do not see) might use them."
+                        + "<br>"
+                        + "Do you really want to unglue?"),
+                tr("You are about to unglue incomplete objects."
+                        + "<br>"
+                        + "This will cause problems because you don''t see the real object."
+                        + "<br>" + "Do you really want to unglue?"),
+                getEditLayer().data.getDataSourceArea(), primitives, null);
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/command/Command.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/Command.java	(revision 4457)
+++ /trunk/src/org/openstreetmap/josm/command/Command.java	(revision 4458)
@@ -2,4 +2,8 @@
 package org.openstreetmap.josm.command;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.geom.Area;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -9,4 +13,7 @@
 import java.util.Map.Entry;
 
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.MutableTreeNode;
@@ -19,4 +26,5 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
+import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
@@ -171,3 +179,64 @@
     }
 
+    /**
+     * Check whether user is about to operate on data outside of the download area.
+     * Request confirmation if he is.
+     *
+     * @param layer the layer in whose context data is deleted
+     * @param primitives the primitives to operate on
+     * @return true, if deleting outlying primitives is OK; false, otherwise
+     */
+    public static boolean checkAndConfirmOutlyingOperation(String operation,
+            String dialogTitle, String outsideDialogMessage, String incompleteDialogMessage,
+            Area area, Collection<? extends OsmPrimitive> primitives, OsmPrimitive ignore) {
+        boolean outside = false;
+        boolean incomplete = false;
+        if (area != null) {
+            for (OsmPrimitive osm : primitives) {
+                if (osm.isIncomplete()) {
+                    incomplete = true;
+                } else if (osm instanceof Node && !osm.isNewOrUndeleted()
+                        && !area.contains(((Node) osm).getCoor())
+                        && (ignore == null || !ignore.equals(osm))) {
+                    outside = true;
+                }
+            }
+        } else {
+            for (OsmPrimitive osm : primitives) {
+                if (osm.isIncomplete()) {
+                    incomplete = true;
+                }
+            }
+        }
+        if (outside) {
+            JPanel msg = new JPanel(new GridBagLayout());
+            msg.add(new JLabel("<html>" + outsideDialogMessage + "</html>"));
+            boolean answer = ConditionalOptionPaneUtil.showConfirmationDialog(
+                    operation + "_outside_nodes",
+                    Main.parent,
+                    msg,
+                    dialogTitle,
+                    JOptionPane.YES_NO_OPTION,
+                    JOptionPane.QUESTION_MESSAGE,
+                    JOptionPane.YES_OPTION);
+            if(!answer)
+                return false;
+        }
+        if (incomplete) {
+            JPanel msg = new JPanel(new GridBagLayout());
+            msg.add(new JLabel("<html>" + incompleteDialogMessage + "</html>"));
+            boolean answer = ConditionalOptionPaneUtil.showConfirmationDialog(
+                    operation + "_incomplete",
+                    Main.parent,
+                    msg,
+                    dialogTitle,
+                    JOptionPane.YES_NO_OPTION,
+                    JOptionPane.QUESTION_MESSAGE,
+                    JOptionPane.YES_OPTION);
+            if(!answer)
+                return false;
+        }
+        return true;
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 4457)
+++ /trunk/src/org/openstreetmap/josm/command/DeleteCommand.java	(revision 4458)
@@ -2,10 +2,9 @@
 package org.openstreetmap.josm.command;
 
+import java.awt.geom.Area;
 import static org.openstreetmap.josm.tools.I18n.marktr;
 import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trn;
 
-import java.awt.GridBagLayout;
-import java.awt.geom.Area;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -21,8 +20,5 @@
 
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import org.openstreetmap.josm.Main;
+
 import org.openstreetmap.josm.actions.SplitWayAction;
 import org.openstreetmap.josm.data.osm.Node;
@@ -34,5 +30,4 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.WaySegment;
-import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
 import org.openstreetmap.josm.gui.actionsupport.DeleteFromRelationConfirmationDialog;
@@ -234,5 +229,5 @@
         if (parents.isEmpty())
             return null;
-        if (!silent && !checkAndConfirmOutlyingDeletes(layer,parents))
+        if (!silent && !checkAndConfirmOutlyingDelete(layer, parents, null))
             return null;
         return new DeleteCommand(layer,parents);
@@ -331,5 +326,5 @@
         }
 
-        if (!silent && !checkAndConfirmOutlyingDeletes(layer,primitivesToDelete))
+        if (!silent && !checkAndConfirmOutlyingDelete(layer, primitivesToDelete, null))
             return null;
 
@@ -427,80 +422,22 @@
     }
 
-    /**
-     * Check whether user is about to delete data outside of the download area. Request confirmation
-     * if he is.
-     *
-     * @param layer the layer in whose context data is deleted
-     * @param primitivesToDelete the primitives to delete
-     * @return true, if deleting outlying primitives is OK; false, otherwise
-     */
-    private static boolean checkAndConfirmOutlyingDeletes(OsmDataLayer layer, Collection<OsmPrimitive> primitivesToDelete) {
-        Area a = layer.data.getDataSourceArea();
-        boolean outside = false;
-        boolean incomplete = false;
-        if (a != null) {
-            for (OsmPrimitive osm : primitivesToDelete) {
-                if (osm.isIncomplete()) {
-                    incomplete = true;
-                } else if (osm instanceof Node && !osm.isNewOrUndeleted()
-                        && !a.contains(((Node) osm).getCoor())) {
-                    outside = true;
-                }
-            }
-        }
-        else
-        {
-            for (OsmPrimitive osm : primitivesToDelete)
-                if (osm.isIncomplete()) {
-                    incomplete = true;
-                }
-        }
-        if(outside)
-        {
-            JPanel msg = new JPanel(new GridBagLayout());
-            msg.add(new JLabel(
-                    "<html>" +
-                    // leave message in one tr() as there is a grammatical
-                    // connection.
-                    tr("You are about to delete nodes outside of the area you have downloaded."
-                            + "<br>"
-                            + "This can cause problems because other objects (that you do not see) might use them."
-                            + "<br>" + "Do you really want to delete?") + "</html>"));
-            boolean answer = ConditionalOptionPaneUtil.showConfirmationDialog(
-                    "delete_outside_nodes",
-                    Main.parent,
-                    msg,
-                    tr("Delete confirmation"),
-                    JOptionPane.YES_NO_OPTION,
-                    JOptionPane.QUESTION_MESSAGE,
-                    JOptionPane.YES_OPTION
-            );
-            if(!answer)
-                return false;
-        }
-        if(incomplete)
-        {
-            JPanel msg = new JPanel(new GridBagLayout());
-            msg.add(new JLabel(
-                    "<html>" +
-                    // leave message in one tr() as there is a grammatical
-                    // connection.
-                    tr("You are about to delete incomplete objects."
-                            + "<br>"
-                            + "This will cause problems because you don''t see the real object."
-                            + "<br>" + "Do you really want to delete?") + "</html>"));
-            boolean answer = ConditionalOptionPaneUtil.showConfirmationDialog(
-                    "delete_incomplete",
-                    Main.parent,
-                    msg,
-                    tr("Delete confirmation"),
-                    JOptionPane.YES_NO_OPTION,
-                    JOptionPane.QUESTION_MESSAGE,
-                    JOptionPane.YES_OPTION
-            );
-            if(!answer)
-                return false;
-        }
-        return true;
-    }
+    public static boolean checkAndConfirmOutlyingDelete(OsmDataLayer layer, Collection<? extends OsmPrimitive> primitives, OsmPrimitive ignore) {
+        return checkAndConfirmOutlyingDelete(layer.data.getDataSourceArea(), primitives, ignore);
+    }
+
+    public static boolean checkAndConfirmOutlyingDelete(Area area, Collection<? extends OsmPrimitive> primitives, OsmPrimitive ignore) {
+        return Command.checkAndConfirmOutlyingOperation("delete",
+                tr("Delete confirmation"),
+                tr("You are about to delete nodes outside of the area you have downloaded."
+                        + "<br>"
+                        + "This can cause problems because other objects (that you do not see) might use them."
+                        + "<br>"
+                        + "Do you really want to delete?"),
+                tr("You are about to delete incomplete objects."
+                        + "<br>"
+                        + "This will cause problems because you don''t see the real object."
+                        + "<br>" + "Do you really want to delete?"),
+                area, primitives, ignore);
+    }
+
 }
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateNode.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateNode.java	(revision 4457)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateNode.java	(revision 4458)
@@ -24,4 +24,5 @@
 import org.openstreetmap.josm.actions.MergeNodesAction;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.Hash;
@@ -390,5 +391,5 @@
         }
 
-        if (checkAndConfirmOutlyingDeletes(nodes, target))
+        if (DeleteCommand.checkAndConfirmOutlyingDelete(Main.main.getCurrentDataSet().getDataSourceArea(), nodes, target))
             return MergeNodesAction.mergeNodes(Main.main.getEditLayer(), nodes, target);
 
@@ -406,39 +407,3 @@
         return true;
     }
-
-    /**
-     * Check whether user is about to delete data outside of the download area.
-     * Request confirmation if he is.
-     */
-    private static boolean checkAndConfirmOutlyingDeletes(LinkedHashSet<Node> del, Node ignore) {
-        Area a = Main.main.getCurrentDataSet().getDataSourceArea();
-        if (a != null) {
-            for (OsmPrimitive osm : del) {
-                if (osm instanceof Node && !osm.isNew() && osm != ignore) {
-                    Node n = (Node) osm;
-                    if (!a.contains(n.getCoor())) {
-                        JPanel msg = new JPanel(new GridBagLayout());
-                        msg.add(new JLabel(
-                                "<html>" +
-                                // leave message in one tr() as there is a grammatical
-                                // connection.
-                                tr("You are about to delete nodes outside of the area you have downloaded."
-                                        + "<br>"
-                                        + "This can cause problems because other objects (that you do not see) might use them."
-                                        + "<br>" + "Do you really want to delete?") + "</html>"));
-
-                        return ConditionalOptionPaneUtil.showConfirmationDialog(
-                                "delete_outside_nodes",
-                                Main.parent,
-                                msg,
-                                tr("Delete confirmation"),
-                                JOptionPane.YES_NO_OPTION,
-                                JOptionPane.QUESTION_MESSAGE,
-                                JOptionPane.YES_OPTION);
-                    }
-                }
-            }
-        }
-        return true;
-    }
 }
