Index: /applications/editors/josm/plugins/wmsplugin/.classpath
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/.classpath	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/.classpath	(revision 22677)
@@ -5,4 +5,5 @@
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/remotecontrol"/>
 	<classpathentry kind="output" path="build"/>
 </classpath>
Index: /applications/editors/josm/plugins/wmsplugin/build.xml
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/build.xml	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/build.xml	(revision 22677)
@@ -33,4 +33,5 @@
 
 	<property name="josm" location="../../core/dist/josm-custom.jar" />
+	<property name="remotecontrol" location="../../dist/remotecontrol.jar" />
 	<property name="plugin.dist.dir" value="../../dist" />
 	<property name="plugin.build.dir" value="build" />
@@ -43,5 +44,5 @@
 	<target name="compile" depends="init">
 		<echo message="creating ${plugin.jar}" />
-		<javac srcdir="src" classpath="${josm}" debug="true" destdir="${plugin.build.dir}">
+		<javac srcdir="src" classpath="${josm};${remotecontrol}" debug="true" destdir="${plugin.build.dir}">
 			<compilerarg value="-Xlint:deprecation" />
 			<compilerarg value="-Xlint:unchecked" />
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/Map_Rectifier_WMSmenuAction.java	(revision 22677)
@@ -29,219 +29,219 @@
 
 public class Map_Rectifier_WMSmenuAction extends JosmAction {
-    /**
-     * Class that bundles all required information of a rectifier service
-     */
-    public static class RectifierService {
-        private final String name;
-        private final String url;
-        private final String wmsUrl;
-        private final Pattern urlRegEx;
-        private final Pattern idValidator;
-        public JRadioButton btn;
-        /**
-         * @param name: Name of the rectifing service
-         * @param url: URL to the service where users can register, upload, etc.
-         * @param wmsUrl: URL to the WMS server where JOSM will grab the images. Insert __s__ where the ID should be placed
-         * @param urlRegEx: a regular expression that determines if a given URL is one of the service and returns the WMS id if so
-         * @param idValidator: regular expression that checks if a given ID is syntactically valid
-         */
-        public RectifierService(String name, String url, String wmsUrl, String urlRegEx, String idValidator) {
-            this.name = name;
-            this.url = url;
-            this.wmsUrl = wmsUrl;
-            this.urlRegEx = Pattern.compile(urlRegEx);
-            this.idValidator = Pattern.compile(idValidator);
-        }
-
-        public boolean isSelected() {
-            return btn.isSelected();
-        }
-    }
-
-    /**
-     * List of available rectifier services. May be extended from the outside
-     */
-    public ArrayList<RectifierService> services = new ArrayList<RectifierService>();
-
-    public Map_Rectifier_WMSmenuAction() {
-        super(tr("Rectified Image..."),
-                "OLmarker",
-                tr("Download Rectified Images From Various Services"),
-                Shortcut.registerShortcut("wms:rectimg",
-                        tr("WMS: {0}", tr("Rectified Image...")),
-                        KeyEvent.VK_R,
-                        Shortcut.GROUP_NONE),
-                        true
-        );
-
-        // Add default services
-        services.add(
-            new RectifierService("Metacarta Map Rectifier",
-                "http://labs.metacarta.com/rectifier/",
-                "http://labs.metacarta.com/rectifier/wms.cgi?id=__s__&srs=EPSG:4326"
-                + "&Service=WMS&Version=1.1.0&Request=GetMap&format=image/png&",
-                // This matches more than the "classic" WMS link, so users can pretty much
-                // copy any link as long as it includes the ID
-                "labs\\.metacarta\\.com/(?:.*?)(?:/|=)([0-9]+)(?:\\?|/|\\.|$)",
-                "^[0-9]+$")
-        );
-        services.add(
-            // TODO: Change all links to mapwarper.net once the project has moved.
-            // The RegEx already matches the new URL and old URLs will be forwarded
-            // to make the transition as smooth as possible for the users
-            new RectifierService("Geothings Map Warper",
-                "http://warper.geothings.net/",
-                "http://warper.geothings.net/maps/wms/__s__?request=GetMap&version=1.1.1"
-                + "&styles=&format=image/png&srs=epsg:4326&exceptions=application/vnd.ogc.se_inimage&",
-                // This matches more than the "classic" WMS link, so users can pretty much
-                // copy any link as long as it includes the ID
-                "(?:mapwarper\\.net|warper\\.geothings\\.net)/(?:.*?)/([0-9]+)(?:\\?|/|\\.|$)",
-                "^[0-9]+$")
-        );
-
-        // This service serves the purpose of "just this once" without forcing the user
-        // to commit the link to the preferences
-
-        // Clipboard content gets trimmed, so matching whitespace only ensures that this
-        // service will never be selected automatically.
-        services.add(new RectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        JPanel panel = new JPanel(new GridBagLayout());
-        panel.add(new JLabel(tr("Supported Rectifier Services:")), GBC.eol());
-
-        JTextField tfWmsUrl = new JTextField(30);
-
-        String clip = getClipboardContents();
-        ButtonGroup group = new ButtonGroup();
-
-        JRadioButton firstBtn = null;
-        for(RectifierService s : services) {
-            JRadioButton serviceBtn = new JRadioButton(s.name);
-            if(firstBtn == null)
-                firstBtn = serviceBtn;
-            // Checks clipboard contents against current service if no match has been found yet.
-            // If the contents match, they will be inserted into the text field and the corresponding
-            // service will be pre-selected.
-            if(!clip.equals("") && tfWmsUrl.getText().equals("")
-                    && (s.urlRegEx.matcher(clip).find() || s.idValidator.matcher(clip).matches())) {
-                serviceBtn.setSelected(true);
-                tfWmsUrl.setText(clip);
-            }
-            s.btn = serviceBtn;
-            group.add(serviceBtn);
-            if(!s.url.equals("")) {
-                panel.add(serviceBtn, GBC.std());
-                panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GridBagConstraints.EAST));
-            } else
-                panel.add(serviceBtn, GBC.eol().anchor(GridBagConstraints.WEST));
-        }
-
-        // Fallback in case no match was found
-        if(tfWmsUrl.getText().equals("") && firstBtn != null)
-            firstBtn.setSelected(true);
-
-        panel.add(new JLabel(tr("WMS URL or Image ID:")), GBC.eol());
-        panel.add(tfWmsUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-
-        ExtendedDialog diag = new ExtendedDialog(Main.parent,
-                tr("Add Rectified Image"),
-
-                new String[] {tr("Add Rectified Image"), tr("Cancel")});
-        diag.setContent(panel);
-        diag.setButtonIcons(new String[] {"OLmarker.png", "cancel.png"});
-
-        // This repeatedly shows the dialog in case there has been an error.
-        // The loop is break;-ed if the users cancels
-        outer: while(true) {
-            diag.showDialog();
-            int answer = diag.getValue();
-            // Break loop when the user cancels
-            if(answer != 1)
-                break;
-
-            String text = tfWmsUrl.getText().trim();
-            // Loop all services until we find the selected one
-            for(RectifierService s : services) {
-                if(!s.isSelected())
-                    continue;
-
-                // We've reached the custom WMS URL service
-                // Just set the URL and hope everything works out
-                if(s.wmsUrl.equals("")) {
-                    addWMSLayer(s.name + " (" + text + ")", text);
-                    break outer;
-                }
-
-                // First try to match if the entered string as an URL
-                Matcher m = s.urlRegEx.matcher(text);
-                if(m.find()) {
-                    String id = m.group(1);
-                    String newURL = s.wmsUrl.replaceAll("__s__", id);
-                    String title = s.name + " (" + id + ")";
-                    addWMSLayer(title, newURL);
-                    break outer;
-                }
-                // If not, look if it's a valid ID for the selected service
-                if(s.idValidator.matcher(text).matches()) {
-                    String newURL = s.wmsUrl.replaceAll("__s__", text);
-                    String title = s.name + " (" + text + ")";
-                    addWMSLayer(title, newURL);
-                    break outer;
-                }
-
-                // We've found the selected service, but the entered string isn't suitable for
-                // it. So quit checking the other radio buttons
-                break;
-            }
-
-            // and display an error message. The while(true) ensures that the dialog pops up again
-            JOptionPane.showMessageDialog(Main.parent,
-                    tr("Couldn't match the entered link or id to the selected service. Please try again."),
-                    tr("No valid WMS URL or id"),
-                    JOptionPane.ERROR_MESSAGE);
-            diag.setVisible(true);
-        }
-    }
-
-    /**
-     * Adds a WMS Layer with given title and URL
-     * @param title: Name of the layer as it will shop up in the layer manager
-     * @param url: URL to the WMS server
-     * @param cookies: Cookies to send with each image request (Format: josm=is; very=cool)
-     */
-    private void addWMSLayer(String title, String url, String cookies) {
-        WMSLayer wmsLayer = new WMSLayer(title, url, cookies);
-        Main.main.addLayer(wmsLayer);
-    }
-
-    /**
-     * Adds a WMS Layer with given title and URL
-     * @param title: Name of the layer as it will shop up in the layer manager
-     * @param url: URL to the WMS server
-     */
-    private void addWMSLayer(String title, String url) {
-        addWMSLayer(title, url, "");
-    }
-
-    /**
-     * Helper function that extracts a String from the Clipboard if available.
-     * Returns an empty String otherwise
-     * @return String Clipboard contents if available
-     */
-    private String getClipboardContents() {
-        String result = "";
-        Transferable contents = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
-
-        if(contents == null || !contents.isDataFlavorSupported(DataFlavor.stringFlavor))
-            return "";
-
-        try {
-            result = (String)contents.getTransferData(DataFlavor.stringFlavor);
-        } catch(Exception ex) {
-            return "";
-        }
-        return result.trim();
-    }
+	/**
+	 * Class that bundles all required information of a rectifier service
+	 */
+	public static class RectifierService {
+		private final String name;
+		private final String url;
+		private final String wmsUrl;
+		private final Pattern urlRegEx;
+		private final Pattern idValidator;
+		public JRadioButton btn;
+		/**
+		 * @param name: Name of the rectifing service
+		 * @param url: URL to the service where users can register, upload, etc.
+		 * @param wmsUrl: URL to the WMS server where JOSM will grab the images. Insert __s__ where the ID should be placed
+		 * @param urlRegEx: a regular expression that determines if a given URL is one of the service and returns the WMS id if so
+		 * @param idValidator: regular expression that checks if a given ID is syntactically valid
+		 */
+		public RectifierService(String name, String url, String wmsUrl, String urlRegEx, String idValidator) {
+			this.name = name;
+			this.url = url;
+			this.wmsUrl = wmsUrl;
+			this.urlRegEx = Pattern.compile(urlRegEx);
+			this.idValidator = Pattern.compile(idValidator);
+		}
+
+		public boolean isSelected() {
+			return btn.isSelected();
+		}
+	}
+
+	/**
+	 * List of available rectifier services. May be extended from the outside
+	 */
+	public ArrayList<RectifierService> services = new ArrayList<RectifierService>();
+
+	public Map_Rectifier_WMSmenuAction() {
+		super(tr("Rectified Image..."),
+				"OLmarker",
+				tr("Download Rectified Images From Various Services"),
+				Shortcut.registerShortcut("wms:rectimg",
+						tr("WMS: {0}", tr("Rectified Image...")),
+						KeyEvent.VK_R,
+						Shortcut.GROUP_NONE),
+						true
+		);
+
+		// Add default services
+		services.add(
+				new RectifierService("Metacarta Map Rectifier",
+						"http://labs.metacarta.com/rectifier/",
+						"http://labs.metacarta.com/rectifier/wms.cgi?id=__s__&srs=EPSG:4326"
+						+ "&Service=WMS&Version=1.1.0&Request=GetMap&format=image/png&",
+						// This matches more than the "classic" WMS link, so users can pretty much
+						// copy any link as long as it includes the ID
+						"labs\\.metacarta\\.com/(?:.*?)(?:/|=)([0-9]+)(?:\\?|/|\\.|$)",
+				"^[0-9]+$")
+		);
+		services.add(
+				// TODO: Change all links to mapwarper.net once the project has moved.
+				// The RegEx already matches the new URL and old URLs will be forwarded
+				// to make the transition as smooth as possible for the users
+				new RectifierService("Geothings Map Warper",
+						"http://warper.geothings.net/",
+						"http://warper.geothings.net/maps/wms/__s__?request=GetMap&version=1.1.1"
+						+ "&styles=&format=image/png&srs=epsg:4326&exceptions=application/vnd.ogc.se_inimage&",
+						// This matches more than the "classic" WMS link, so users can pretty much
+						// copy any link as long as it includes the ID
+						"(?:mapwarper\\.net|warper\\.geothings\\.net)/(?:.*?)/([0-9]+)(?:\\?|/|\\.|$)",
+				"^[0-9]+$")
+		);
+
+		// This service serves the purpose of "just this once" without forcing the user
+		// to commit the link to the preferences
+
+		// Clipboard content gets trimmed, so matching whitespace only ensures that this
+		// service will never be selected automatically.
+		services.add(new RectifierService(tr("Custom WMS Link"), "", "", "^\\s+$", ""));
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		JPanel panel = new JPanel(new GridBagLayout());
+		panel.add(new JLabel(tr("Supported Rectifier Services:")), GBC.eol());
+
+		JTextField tfWmsUrl = new JTextField(30);
+
+		String clip = getClipboardContents();
+		ButtonGroup group = new ButtonGroup();
+
+		JRadioButton firstBtn = null;
+		for(RectifierService s : services) {
+			JRadioButton serviceBtn = new JRadioButton(s.name);
+			if(firstBtn == null)
+				firstBtn = serviceBtn;
+			// Checks clipboard contents against current service if no match has been found yet.
+			// If the contents match, they will be inserted into the text field and the corresponding
+			// service will be pre-selected.
+			if(!clip.equals("") && tfWmsUrl.getText().equals("")
+					&& (s.urlRegEx.matcher(clip).find() || s.idValidator.matcher(clip).matches())) {
+				serviceBtn.setSelected(true);
+				tfWmsUrl.setText(clip);
+			}
+			s.btn = serviceBtn;
+			group.add(serviceBtn);
+			if(!s.url.equals("")) {
+				panel.add(serviceBtn, GBC.std());
+				panel.add(new UrlLabel(s.url, tr("Visit Homepage")), GBC.eol().anchor(GridBagConstraints.EAST));
+			} else
+				panel.add(serviceBtn, GBC.eol().anchor(GridBagConstraints.WEST));
+		}
+
+		// Fallback in case no match was found
+		if(tfWmsUrl.getText().equals("") && firstBtn != null)
+			firstBtn.setSelected(true);
+
+		panel.add(new JLabel(tr("WMS URL or Image ID:")), GBC.eol());
+		panel.add(tfWmsUrl, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+
+		ExtendedDialog diag = new ExtendedDialog(Main.parent,
+				tr("Add Rectified Image"),
+
+				new String[] {tr("Add Rectified Image"), tr("Cancel")});
+		diag.setContent(panel);
+		diag.setButtonIcons(new String[] {"OLmarker.png", "cancel.png"});
+
+		// This repeatedly shows the dialog in case there has been an error.
+		// The loop is break;-ed if the users cancels
+		outer: while(true) {
+			diag.showDialog();
+			int answer = diag.getValue();
+			// Break loop when the user cancels
+			if(answer != 1)
+				break;
+
+			String text = tfWmsUrl.getText().trim();
+			// Loop all services until we find the selected one
+			for(RectifierService s : services) {
+				if(!s.isSelected())
+					continue;
+
+				// We've reached the custom WMS URL service
+				// Just set the URL and hope everything works out
+				if(s.wmsUrl.equals("")) {
+					addWMSLayer(s.name + " (" + text + ")", text);
+					break outer;
+				}
+
+				// First try to match if the entered string as an URL
+				Matcher m = s.urlRegEx.matcher(text);
+				if(m.find()) {
+					String id = m.group(1);
+					String newURL = s.wmsUrl.replaceAll("__s__", id);
+					String title = s.name + " (" + id + ")";
+					addWMSLayer(title, newURL);
+					break outer;
+				}
+				// If not, look if it's a valid ID for the selected service
+				if(s.idValidator.matcher(text).matches()) {
+					String newURL = s.wmsUrl.replaceAll("__s__", text);
+					String title = s.name + " (" + text + ")";
+					addWMSLayer(title, newURL);
+					break outer;
+				}
+
+				// We've found the selected service, but the entered string isn't suitable for
+				// it. So quit checking the other radio buttons
+				break;
+			}
+
+			// and display an error message. The while(true) ensures that the dialog pops up again
+			JOptionPane.showMessageDialog(Main.parent,
+					tr("Couldn't match the entered link or id to the selected service. Please try again."),
+					tr("No valid WMS URL or id"),
+					JOptionPane.ERROR_MESSAGE);
+			diag.setVisible(true);
+		}
+	}
+
+	/**
+	 * Adds a WMS Layer with given title and URL
+	 * @param title: Name of the layer as it will shop up in the layer manager
+	 * @param url: URL to the WMS server
+	 * @param cookies: Cookies to send with each image request (Format: josm=is; very=cool)
+	 */
+	private void addWMSLayer(String title, String url, String cookies) {
+		WMSLayer wmsLayer = new WMSLayer(title, url, cookies);
+		Main.main.addLayer(wmsLayer);
+	}
+
+	/**
+	 * Adds a WMS Layer with given title and URL
+	 * @param title: Name of the layer as it will shop up in the layer manager
+	 * @param url: URL to the WMS server
+	 */
+	private void addWMSLayer(String title, String url) {
+		addWMSLayer(title, url, "");
+	}
+
+	/**
+	 * Helper function that extracts a String from the Clipboard if available.
+	 * Returns an empty String otherwise
+	 * @return String Clipboard contents if available
+	 */
+	private String getClipboardContents() {
+		String result = "";
+		Transferable contents = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
+
+		if(contents == null || !contents.isDataFlavorSupported(DataFlavor.stringFlavor))
+			return "";
+
+		try {
+			result = (String)contents.getTransferData(DataFlavor.stringFlavor);
+		} catch(Exception ex) {
+			return "";
+		}
+		return result.trim();
+	}
 }
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSAdjustAction.java	(revision 22677)
@@ -31,188 +31,188 @@
 
 public class WMSAdjustAction extends MapMode implements MouseListener, MouseMotionListener{
-    //static private final Logger logger = Logger.getLogger(WMSAdjustAction.class.getName());
-
-    GeorefImage selectedImage;
-    boolean mouseDown;
-    EastNorth prevEastNorth;
-    private WMSLayer adjustingLayer;
-
-    public WMSAdjustAction(MapFrame mapFrame) {
-        super(tr("Adjust WMS"), "adjustwms",
-                        tr("Adjust the position of the selected WMS layer"), mapFrame,
-                        ImageProvider.getCursor("normal", "move"));
-    }
-
-
-
-    @Override public void enterMode() {
-        super.enterMode();
-        if (!hasWMSLayersToAdjust()) {
-            warnNoWMSLayers();
-            return;
-        }
-        List<WMSLayer> wmsLayers = Main.map.mapView.getLayersOfType(WMSLayer.class);
-        if (wmsLayers.size() == 1) {
-            adjustingLayer = wmsLayers.get(0);
-        } else {
-            adjustingLayer = (WMSLayer)askAdjustLayer(Main.map.mapView.getLayersOfType(WMSLayer.class));
-        }
-        if (adjustingLayer == null)
-            return;
-        if (!adjustingLayer.isVisible()) {
-            adjustingLayer.setVisible(true);
-        }
-        Main.map.mapView.addMouseListener(this);
-        Main.map.mapView.addMouseMotionListener(this);
-    }
-
-    @Override public void exitMode() {
-        super.exitMode();
-        Main.map.mapView.removeMouseListener(this);
-        Main.map.mapView.removeMouseMotionListener(this);
-        adjustingLayer = null;
-    }
-
-    @Override public void mousePressed(MouseEvent e) {
-        if (e.getButton() != MouseEvent.BUTTON1)
-            return;
-
-        if (adjustingLayer.isVisible()) {
-            prevEastNorth=Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            selectedImage = adjustingLayer.findImage(prevEastNorth);
-            if(selectedImage!=null) {
-                Main.map.mapView.setCursor
-                    (Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
-            }
-        }
-    }
-
-    @Override public void mouseDragged(MouseEvent e) {
-        if(selectedImage!=null) {
-            EastNorth eastNorth=
-                    Main.map.mapView.getEastNorth(e.getX(),e.getY());
-            adjustingLayer.displace(
-                eastNorth.east()-prevEastNorth.east(),
-                eastNorth.north()-prevEastNorth.north()
-            );
-            prevEastNorth = eastNorth;
-            Main.map.mapView.repaint();
-        }
-    }
-
-    @Override public void mouseReleased(MouseEvent e) {
-        Main.map.mapView.repaint();
-        Main.map.mapView.setCursor(Cursor.getDefaultCursor());
-        selectedImage = null;
-        prevEastNorth = null;
-    }
-
-    @Override
-    public void mouseEntered(MouseEvent e) {
-    }
-
-    @Override
-    public void mouseExited(MouseEvent e) {
-    }
-
-    @Override
-    public void mouseMoved(MouseEvent e) {
-    }
-
-    @Override public void mouseClicked(MouseEvent e) {
-    }
-
-    // This only makes the buttons look disabled, but since no keyboard shortcut is
-    // provided there aren't any other means to activate this tool
-    @Override public boolean layerIsSupported(Layer l) {
-        return (l instanceof WMSLayer) && l.isVisible();
-    }
-
-    /**
-    * the list cell renderer used to render layer list entries
-    *
-    */
-   static public class LayerListCellRenderer extends DefaultListCellRenderer {
-
-       protected boolean isActiveLayer(Layer layer) {
-           if (Main.map == null)
-               return false;
-           if (Main.map.mapView == null)
-               return false;
-           return Main.map.mapView.getActiveLayer() == layer;
-       }
-
-       @Override
-       public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
-               boolean cellHasFocus) {
-           Layer layer = (Layer) value;
-           JLabel label = (JLabel) super.getListCellRendererComponent(list, layer.getName(), index, isSelected,
-                   cellHasFocus);
-           Icon icon = layer.getIcon();
-           label.setIcon(icon);
-           label.setToolTipText(layer.getToolTipText());
-           return label;
-       }
-   }
-
-   /**
-    * Prompts the user with a list of WMS layers which can be adjusted
-    *
-    * @param adjustableLayers the list of adjustable layers
-    * @return  the selected layer; null, if no layer was selected
-    */
-   protected Layer askAdjustLayer(List<? extends Layer> adjustableLayers) {
-       JComboBox layerList = new JComboBox();
-       layerList.setRenderer(new LayerListCellRenderer());
-       layerList.setModel(new DefaultComboBoxModel(adjustableLayers.toArray()));
-       layerList.setSelectedIndex(0);
-
-       JPanel pnl = new JPanel();
-       pnl.setLayout(new GridBagLayout());
-       pnl.add(new JLabel(tr("Please select the WMS layer to adjust.")), GBC.eol());
-       pnl.add(layerList, GBC.eol());
-
-       ExtendedDialog diag = new ExtendedDialog(
-               Main.parent,
-               tr("Select WMS layer"),
-               new String[] { tr("Start adjusting"),tr("Cancel") }
-               );
-       diag.setContent(pnl);
-       diag.setButtonIcons(new String[] { "mapmode/adjustwms", "cancel" });
-       diag.showDialog();
-       int decision = diag.getValue();
-       if (decision != 1)
-           return null;
-       Layer adjustLayer = (Layer) layerList.getSelectedItem();
-       return adjustLayer;
-   }
-
-   /**
-    * Displays a warning message if there are no WMS layers to adjust
-    *
-    */
-   protected void warnNoWMSLayers() {
-       JOptionPane.showMessageDialog(
-               Main.parent,
-               tr("There are currently no WMS layer to adjust."),
-               tr("No layers to adjust"),
-               JOptionPane.WARNING_MESSAGE
-       );
-   }
-
-   /**
-    * Replies true if there is at least one WMS layer
-    *
-    * @return true if there is at least one WMS layer
-    */
-   protected boolean hasWMSLayersToAdjust() {
-       if (Main.map == null) return false;
-       if (Main.map.mapView == null) return false;
-       return ! Main.map.mapView.getLayersOfType(WMSLayer.class).isEmpty();
-   }
-
-    @Override
-    protected void updateEnabledState() {
-        setEnabled(hasWMSLayersToAdjust());
-    }
+	//static private final Logger logger = Logger.getLogger(WMSAdjustAction.class.getName());
+
+	GeorefImage selectedImage;
+	boolean mouseDown;
+	EastNorth prevEastNorth;
+	private WMSLayer adjustingLayer;
+
+	public WMSAdjustAction(MapFrame mapFrame) {
+		super(tr("Adjust WMS"), "adjustwms",
+				tr("Adjust the position of the selected WMS layer"), mapFrame,
+				ImageProvider.getCursor("normal", "move"));
+	}
+
+
+
+	@Override public void enterMode() {
+		super.enterMode();
+		if (!hasWMSLayersToAdjust()) {
+			warnNoWMSLayers();
+			return;
+		}
+		List<WMSLayer> wmsLayers = Main.map.mapView.getLayersOfType(WMSLayer.class);
+		if (wmsLayers.size() == 1) {
+			adjustingLayer = wmsLayers.get(0);
+		} else {
+			adjustingLayer = (WMSLayer)askAdjustLayer(Main.map.mapView.getLayersOfType(WMSLayer.class));
+		}
+		if (adjustingLayer == null)
+			return;
+		if (!adjustingLayer.isVisible()) {
+			adjustingLayer.setVisible(true);
+		}
+		Main.map.mapView.addMouseListener(this);
+		Main.map.mapView.addMouseMotionListener(this);
+	}
+
+	@Override public void exitMode() {
+		super.exitMode();
+		Main.map.mapView.removeMouseListener(this);
+		Main.map.mapView.removeMouseMotionListener(this);
+		adjustingLayer = null;
+	}
+
+	@Override public void mousePressed(MouseEvent e) {
+		if (e.getButton() != MouseEvent.BUTTON1)
+			return;
+
+		if (adjustingLayer.isVisible()) {
+			prevEastNorth=Main.map.mapView.getEastNorth(e.getX(),e.getY());
+			selectedImage = adjustingLayer.findImage(prevEastNorth);
+			if(selectedImage!=null) {
+				Main.map.mapView.setCursor
+				(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+			}
+		}
+	}
+
+	@Override public void mouseDragged(MouseEvent e) {
+		if(selectedImage!=null) {
+			EastNorth eastNorth=
+				Main.map.mapView.getEastNorth(e.getX(),e.getY());
+			adjustingLayer.displace(
+					eastNorth.east()-prevEastNorth.east(),
+					eastNorth.north()-prevEastNorth.north()
+			);
+			prevEastNorth = eastNorth;
+			Main.map.mapView.repaint();
+		}
+	}
+
+	@Override public void mouseReleased(MouseEvent e) {
+		Main.map.mapView.repaint();
+		Main.map.mapView.setCursor(Cursor.getDefaultCursor());
+		selectedImage = null;
+		prevEastNorth = null;
+	}
+
+	@Override
+	public void mouseEntered(MouseEvent e) {
+	}
+
+	@Override
+	public void mouseExited(MouseEvent e) {
+	}
+
+	@Override
+	public void mouseMoved(MouseEvent e) {
+	}
+
+	@Override public void mouseClicked(MouseEvent e) {
+	}
+
+	// This only makes the buttons look disabled, but since no keyboard shortcut is
+	// provided there aren't any other means to activate this tool
+	@Override public boolean layerIsSupported(Layer l) {
+		return (l instanceof WMSLayer) && l.isVisible();
+	}
+
+	/**
+	 * the list cell renderer used to render layer list entries
+	 *
+	 */
+	static public class LayerListCellRenderer extends DefaultListCellRenderer {
+
+		protected boolean isActiveLayer(Layer layer) {
+			if (Main.map == null)
+				return false;
+			if (Main.map.mapView == null)
+				return false;
+			return Main.map.mapView.getActiveLayer() == layer;
+		}
+
+		@Override
+		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+				boolean cellHasFocus) {
+			Layer layer = (Layer) value;
+			JLabel label = (JLabel) super.getListCellRendererComponent(list, layer.getName(), index, isSelected,
+					cellHasFocus);
+			Icon icon = layer.getIcon();
+			label.setIcon(icon);
+			label.setToolTipText(layer.getToolTipText());
+			return label;
+		}
+	}
+
+	/**
+	 * Prompts the user with a list of WMS layers which can be adjusted
+	 *
+	 * @param adjustableLayers the list of adjustable layers
+	 * @return  the selected layer; null, if no layer was selected
+	 */
+	protected Layer askAdjustLayer(List<? extends Layer> adjustableLayers) {
+		JComboBox layerList = new JComboBox();
+		layerList.setRenderer(new LayerListCellRenderer());
+		layerList.setModel(new DefaultComboBoxModel(adjustableLayers.toArray()));
+		layerList.setSelectedIndex(0);
+
+		JPanel pnl = new JPanel();
+		pnl.setLayout(new GridBagLayout());
+		pnl.add(new JLabel(tr("Please select the WMS layer to adjust.")), GBC.eol());
+		pnl.add(layerList, GBC.eol());
+
+		ExtendedDialog diag = new ExtendedDialog(
+				Main.parent,
+				tr("Select WMS layer"),
+				new String[] { tr("Start adjusting"),tr("Cancel") }
+		);
+		diag.setContent(pnl);
+		diag.setButtonIcons(new String[] { "mapmode/adjustwms", "cancel" });
+		diag.showDialog();
+		int decision = diag.getValue();
+		if (decision != 1)
+			return null;
+		Layer adjustLayer = (Layer) layerList.getSelectedItem();
+		return adjustLayer;
+	}
+
+	/**
+	 * Displays a warning message if there are no WMS layers to adjust
+	 *
+	 */
+	protected void warnNoWMSLayers() {
+		JOptionPane.showMessageDialog(
+				Main.parent,
+				tr("There are currently no WMS layer to adjust."),
+				tr("No layers to adjust"),
+				JOptionPane.WARNING_MESSAGE
+		);
+	}
+
+	/**
+	 * Replies true if there is at least one WMS layer
+	 *
+	 * @return true if there is at least one WMS layer
+	 */
+	protected boolean hasWMSLayersToAdjust() {
+		if (Main.map == null) return false;
+		if (Main.map.mapView == null) return false;
+		return ! Main.map.mapView.getLayersOfType(WMSLayer.class).isEmpty();
+	}
+
+	@Override
+	protected void updateEnabledState() {
+		setEnabled(hasWMSLayersToAdjust());
+	}
 }
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSDownloadAction.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSDownloadAction.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSDownloadAction.java	(revision 22677)
@@ -10,24 +10,24 @@
 public class WMSDownloadAction extends JosmAction {
 
-    private final WMSInfo info;
+	private final WMSInfo info;
 
-    public WMSDownloadAction(WMSInfo info) {
-        super(info.name, "wmsmenu", tr("Download WMS tile from {0}",info.name), null, false);
-        putValue("toolbar", "wms_" + info.name);
-        this.info = info;
-    }
+	public WMSDownloadAction(WMSInfo info) {
+		super(info.name, "wmsmenu", tr("Download WMS tile from {0}",info.name), null, false);
+		putValue("toolbar", "wms_" + info.name);
+		this.info = info;
+	}
 
-    public void actionPerformed(ActionEvent e) {
-        //System.out.println(info.url);
+	public void actionPerformed(ActionEvent e) {
+		//System.out.println(info.url);
 
-        WMSLayer wmsLayer = new WMSLayer(info.name, info.url, info.cookies);
-        Main.main.addLayer(wmsLayer);
-    }
+		WMSLayer wmsLayer = new WMSLayer(info.name, info.url, info.cookies);
+		Main.main.addLayer(wmsLayer);
+	}
 
-    public static WMSLayer getLayer(WMSInfo info) {
-        // FIXME: move this to WMSPlugin/WMSInfo/preferences.
-        WMSLayer wmsLayer = new WMSLayer(info.name, info.url, info.cookies);
-        Main.main.addLayer(wmsLayer);
-        return wmsLayer;
-    }
+	public static WMSLayer getLayer(WMSInfo info) {
+		// FIXME: move this to WMSPlugin/WMSInfo/preferences.
+		WMSLayer wmsLayer = new WMSLayer(info.name, info.url, info.cookies);
+		Main.main.addLayer(wmsLayer);
+		return wmsLayer;
+	}
 };
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSLayer.java	(revision 22677)
@@ -29,7 +29,7 @@
 import org.openstreetmap.josm.actions.SaveActionBase;
 import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent;
 import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener;
+import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
@@ -310,4 +310,5 @@
 
 	public class DownloadAction extends AbstractAction {
+		private static final long serialVersionUID = -7183852461015284020L;
 		public DownloadAction() {
 			super(tr("Download visible tiles"));
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPlugin.java	(revision 22677)
@@ -36,5 +36,8 @@
 import org.openstreetmap.josm.io.MirroredInputStream;
 import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.PluginProxy;
+import org.openstreetmap.josm.plugins.remotecontrol.RemoteControlPlugin;
 
 import wmsplugin.io.WMSLayerExporter;
@@ -42,219 +45,263 @@
 
 public class WMSPlugin extends Plugin {
-    static CacheFiles cache = new CacheFiles("wmsplugin");
-
-    WMSLayer wmsLayer;
-    static JMenu wmsJMenu;
-
-    static ArrayList<WMSInfo> wmsList = new ArrayList<WMSInfo>();
-    static TreeMap<String,String> wmsListDefault = new TreeMap<String,String>();
-
-    static boolean doOverlap = false;
-    static int overlapEast = 14;
-    static int overlapNorth = 4;
-    static int simultaneousConnections = 3;
-
-    // remember state of menu item to restore on changed preferences
-    static private boolean menuEnabled = false;
-
-    protected void initExporterAndImporter() {
-        ExtensionFileFilter.exporters.add(new WMSLayerExporter());
-        ExtensionFileFilter.importers.add(new WMSLayerImporter());
-    }
-
-    public WMSPlugin(PluginInformation info) {
-    	super(info);
-        refreshMenu();
-        cache.setExpire(CacheFiles.EXPIRE_MONTHLY, false);
-        cache.setMaxSize(70, false);
-        initExporterAndImporter();
-    }
-
-    // this parses the preferences settings. preferences for the wms plugin have to
-    // look like this:
-    // wmsplugin.1.name=Landsat
-    // wmsplugin.1.url=http://and.so.on/
-
-    @Override
-    public void copy(String from, String to) throws FileNotFoundException, IOException
-    {
-        File pluginDir = new File(getPrefsPath());
-        if (!pluginDir.exists())
-            pluginDir.mkdirs();
-        FileOutputStream out = new FileOutputStream(getPrefsPath() + to);
-        InputStream in = WMSPlugin.class.getResourceAsStream(from);
-        byte[] buffer = new byte[8192];
-        for(int len = in.read(buffer); len > 0; len = in.read(buffer))
-            out.write(buffer, 0, len);
-        in.close();
-        out.close();
-    }
-
-
-    public static void refreshMenu() {
-        wmsList.clear();
-        Map<String,String> prefs = Main.pref.getAllPrefix("wmsplugin.url.");
-
-        TreeSet<String> keys = new TreeSet<String>(prefs.keySet());
-
-        // Here we load the settings for "overlap" checkbox and spinboxes.
-
-        try {
-            doOverlap = Boolean.valueOf(prefs.get("wmsplugin.url.overlap"));
-        } catch (Exception e) {} // If sth fails, we drop to default settings.
-
-        try {
-            overlapEast = Integer.valueOf(prefs.get("wmsplugin.url.overlapEast"));
-        } catch (Exception e) {} // If sth fails, we drop to default settings.
-
-        try {
-            overlapNorth = Integer.valueOf(prefs.get("wmsplugin.url.overlapNorth"));
-        } catch (Exception e) {} // If sth fails, we drop to default settings.
-               
-        // Load the settings for number of simultaneous connections
-        try {
-            simultaneousConnections = Integer.valueOf(prefs.get("wmsplugin.simultanousConnections"));
-        } catch (Exception e) {} // If sth fails, we drop to default settings.
-
-        // And then the names+urls of WMS servers
-        int prefid = 0;
-        String name = null;
-        String url = null;
-        String cookies = "";
-        int lastid = -1;
-        for (String key : keys) {
-            String[] elements = key.split("\\.");
-            if (elements.length != 4) continue;
-            try {
-                prefid = Integer.parseInt(elements[2]);
-            } catch(NumberFormatException e) {
-                continue;
-            }
-            if (prefid != lastid) {
-                name = url = null; lastid = prefid;
-            }
-            if (elements[3].equals("name"))
-                name = prefs.get(key);
-            else if (elements[3].equals("url"))
-            {
-                /* FIXME: Remove the if clause after some time */
-                if(!prefs.get(key).startsWith("yahoo:")) /* legacy stuff */
-                    url = prefs.get(key);
-            }
-            else if (elements[3].equals("cookies"))
-                cookies = prefs.get(key);
-            if (name != null && url != null)
-                wmsList.add(new WMSInfo(name, url, cookies, prefid));
-        }
-        String source = "http://svn.openstreetmap.org/applications/editors/josm/plugins/wmsplugin/sources.cfg";
-        try
-        {
-            MirroredInputStream s = new MirroredInputStream(source,
-                    Main.pref.getPreferencesDir() + "plugins/wmsplugin/", -1);
-            InputStreamReader r;
-            try
-            {
-                r = new InputStreamReader(s, "UTF-8");
-            }
-            catch (UnsupportedEncodingException e)
-            {
-                r = new InputStreamReader(s);
-            }
-            BufferedReader reader = new BufferedReader(r);
-            String line;
-            while((line = reader.readLine()) != null)
-            {
-                String val[] = line.split(";");
-                if(!line.startsWith("#") && val.length == 3)
-                    setDefault("true".equals(val[0]), tr(val[1]), val[2]);
-            }
-        }
-        catch (IOException e)
-        {
-        }
-
-        Collections.sort(wmsList);
-        MainMenu menu = Main.main.menu;
-
-        if (wmsJMenu == null)
-            wmsJMenu = menu.addMenu(marktr("WMS"), KeyEvent.VK_W, menu.defaultMenuPos, ht("/Plugin/WMS"));
-        else
-            wmsJMenu.removeAll();
-
-        // for each configured WMSInfo, add a menu entry.
-        for (final WMSInfo u : wmsList) {
-            wmsJMenu.add(new JMenuItem(new WMSDownloadAction(u)));
-        }
-        wmsJMenu.addSeparator();
-        wmsJMenu.add(new JMenuItem(new Map_Rectifier_WMSmenuAction()));
-
-        wmsJMenu.addSeparator();
-        wmsJMenu.add(new JMenuItem(new
-                JosmAction(tr("Blank Layer"), "blankmenu", tr("Open a blank WMS layer to load data from a file"), null, false) {
-            public void actionPerformed(ActionEvent ev) {
-                Main.main.addLayer(new WMSLayer());
-            }
-        }));
-        setEnabledAll(menuEnabled);
-    }
-
-    /* add a default entry in case the URL does not yet exist */
-    private static void setDefault(Boolean force, String name, String url)
-    {
-        String testurl = url.replaceAll("=", "_");
-        wmsListDefault.put(name, url);
-
-        if(force && !Main.pref.getBoolean("wmsplugin.default."+testurl))
-        {
-            Main.pref.put("wmsplugin.default."+testurl, true);
-            int id = -1;
-            for(WMSInfo i : wmsList)
-            {
-                if(url.equals(i.url))
-                    return;
-                if(i.prefid > id)
-                    id = i.prefid;
-            }
-            WMSInfo newinfo = new WMSInfo(name, url, id+1);
-            newinfo.save();
-            wmsList.add(newinfo);
-        }
-    }
-
-    public static Grabber getGrabber(ProjectionBounds bounds, GeorefImage img, MapView mv, WMSLayer layer){
-        if(layer.baseURL.startsWith("html:"))
-            return new HTMLGrabber(bounds, img, mv, layer, cache);
-        else
-            return new WMSGrabber(bounds, img, mv, layer, cache);
-    }
-
-    private static void setEnabledAll(boolean isEnabled) {
-        for(int i=0; i < wmsJMenu.getItemCount(); i++) {
-            JMenuItem item = wmsJMenu.getItem(i);
-
-            if(item != null) item.setEnabled(isEnabled);
-        }
-        menuEnabled = isEnabled;
-    }
-
-    @Override
-    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-        if (oldFrame==null && newFrame!=null) {
-            setEnabledAll(true);
-            Main.map.addMapMode(new IconToggleButton
-                    (new WMSAdjustAction(Main.map)));
-        } else if (oldFrame!=null && newFrame==null ) {
-            setEnabledAll(false);
-        }
-    }
-
-    @Override
-    public PreferenceSetting getPreferenceSetting() {
-        return new WMSPreferenceEditor();
-    }
-
-    static public String getPrefsPath()
-    {
-        return Main.pref.getPluginsDirectory().getPath() + "/wmsplugin/";
-    }
+	static CacheFiles cache = new CacheFiles("wmsplugin");
+
+	WMSLayer wmsLayer;
+	static JMenu wmsJMenu;
+
+	static ArrayList<WMSInfo> wmsList = new ArrayList<WMSInfo>();
+	static TreeMap<String,String> wmsListDefault = new TreeMap<String,String>();
+
+	static boolean doOverlap = false;
+	static int overlapEast = 14;
+	static int overlapNorth = 4;
+	static int simultaneousConnections = 3;
+	// remember state of menu item to restore on changed preferences
+	static private boolean menuEnabled = false;
+
+	static boolean remoteControlAvailable = false;
+
+	protected void initExporterAndImporter() {
+		ExtensionFileFilter.exporters.add(new WMSLayerExporter());
+		ExtensionFileFilter.importers.add(new WMSLayerImporter());
+	}
+
+	public WMSPlugin(PluginInformation info) {
+		super(info);
+		/*
+		System.out.println("constructor " + this.getClass().getName() + " (" + info.name +
+				" v " + info.version + " stage " + info.stage + ")");
+		 */
+		refreshMenu();
+		cache.setExpire(CacheFiles.EXPIRE_MONTHLY, false);
+		cache.setMaxSize(70, false);
+		initExporterAndImporter();
+		initRemoteControl();
+	}
+
+	/**
+	 * Check if remotecontrol plug-in is available and if its version is
+	 * high enough and add handler for "wms" remote control command "wms".
+	 */
+	private void initRemoteControl() {
+		final String remotecontrolName = "remotecontrol";
+		final String remotecontrolVersion = "22675";
+		for(PluginProxy pp: PluginHandler.pluginList)
+		{
+			PluginInformation info = pp.getPluginInformation();
+			if(remotecontrolName.equals(info.name))
+			{
+				if(remotecontrolVersion.compareTo(info.version) <= 0)
+				{
+					remoteControlAvailable = true;
+				}
+				else
+				{
+					System.out.println("wmsplugin: remote control plugin version is " +
+							info.version + ", need " + remotecontrolVersion + " or newer");
+				}
+				break;
+			}
+		}
+
+		if(remoteControlAvailable)
+		{
+			System.out.println("wmsplugin: initializing remote control");
+			RemoteControlPlugin plugin =
+				(RemoteControlPlugin) PluginHandler.getPlugin(remotecontrolName);
+			plugin.addRequestHandler(WMSRemoteHandler.command, WMSRemoteHandler.class);
+		}
+		else
+		{
+			System.out.println("wmsplugin: cannot use remote control");
+		}
+	}
+
+	// this parses the preferences settings. preferences for the wms plugin have to
+	// look like this:
+	// wmsplugin.1.name=Landsat
+	// wmsplugin.1.url=http://and.so.on/
+
+	@Override
+	public void copy(String from, String to) throws FileNotFoundException, IOException
+	{
+		File pluginDir = new File(getPrefsPath());
+		if (!pluginDir.exists())
+			pluginDir.mkdirs();
+		FileOutputStream out = new FileOutputStream(getPrefsPath() + to);
+		InputStream in = WMSPlugin.class.getResourceAsStream(from);
+		byte[] buffer = new byte[8192];
+		for(int len = in.read(buffer); len > 0; len = in.read(buffer))
+			out.write(buffer, 0, len);
+		in.close();
+		out.close();
+	}
+
+
+	public static void refreshMenu() {
+		wmsList.clear();
+		Map<String,String> prefs = Main.pref.getAllPrefix("wmsplugin.url.");
+
+		TreeSet<String> keys = new TreeSet<String>(prefs.keySet());
+
+		// Here we load the settings for "overlap" checkbox and spinboxes.
+
+		try {
+			doOverlap = Boolean.valueOf(prefs.get("wmsplugin.url.overlap"));
+		} catch (Exception e) {} // If sth fails, we drop to default settings.
+
+		try {
+			overlapEast = Integer.valueOf(prefs.get("wmsplugin.url.overlapEast"));
+		} catch (Exception e) {} // If sth fails, we drop to default settings.
+
+		try {
+			overlapNorth = Integer.valueOf(prefs.get("wmsplugin.url.overlapNorth"));
+		} catch (Exception e) {} // If sth fails, we drop to default settings.
+
+		// Load the settings for number of simultaneous connections
+		try {
+			simultaneousConnections = Integer.valueOf(Main.pref.get("wmsplugin.simultanousConnections"));
+		} catch (Exception e) {} // If sth fails, we drop to default settings.
+
+		// And then the names+urls of WMS servers
+		int prefid = 0;
+		String name = null;
+		String url = null;
+		String cookies = "";
+		int lastid = -1;
+		for (String key : keys) {
+			String[] elements = key.split("\\.");
+			if (elements.length != 4) continue;
+			try {
+				prefid = Integer.parseInt(elements[2]);
+			} catch(NumberFormatException e) {
+				continue;
+			}
+			if (prefid != lastid) {
+				name = url = null; lastid = prefid;
+			}
+			if (elements[3].equals("name"))
+				name = prefs.get(key);
+			else if (elements[3].equals("url"))
+			{
+				/* FIXME: Remove the if clause after some time */
+				if(!prefs.get(key).startsWith("yahoo:")) /* legacy stuff */
+					url = prefs.get(key);
+			}
+			else if (elements[3].equals("cookies"))
+				cookies = prefs.get(key);
+			if (name != null && url != null)
+				wmsList.add(new WMSInfo(name, url, cookies, prefid));
+		}
+		String source = "http://svn.openstreetmap.org/applications/editors/josm/plugins/wmsplugin/sources.cfg";
+		try
+		{
+			MirroredInputStream s = new MirroredInputStream(source,
+					Main.pref.getPreferencesDir() + "plugins/wmsplugin/", -1);
+			InputStreamReader r;
+			try
+			{
+				r = new InputStreamReader(s, "UTF-8");
+			}
+			catch (UnsupportedEncodingException e)
+			{
+				r = new InputStreamReader(s);
+			}
+			BufferedReader reader = new BufferedReader(r);
+			String line;
+			while((line = reader.readLine()) != null)
+			{
+				String val[] = line.split(";");
+				if(!line.startsWith("#") && val.length == 3)
+					setDefault("true".equals(val[0]), tr(val[1]), val[2]);
+			}
+		}
+		catch (IOException e)
+		{
+		}
+
+		Collections.sort(wmsList);
+		MainMenu menu = Main.main.menu;
+
+		if (wmsJMenu == null)
+			wmsJMenu = menu.addMenu(marktr("WMS"), KeyEvent.VK_W, menu.defaultMenuPos, ht("/Plugin/WMS"));
+		else
+			wmsJMenu.removeAll();
+
+		// for each configured WMSInfo, add a menu entry.
+		for (final WMSInfo u : wmsList) {
+			wmsJMenu.add(new JMenuItem(new WMSDownloadAction(u)));
+		}
+		wmsJMenu.addSeparator();
+		wmsJMenu.add(new JMenuItem(new Map_Rectifier_WMSmenuAction()));
+
+		wmsJMenu.addSeparator();
+		wmsJMenu.add(new JMenuItem(new
+				JosmAction(tr("Blank Layer"), "blankmenu", tr("Open a blank WMS layer to load data from a file"), null, false) {
+			public void actionPerformed(ActionEvent ev) {
+				Main.main.addLayer(new WMSLayer());
+			}
+		}));
+		setEnabledAll(menuEnabled);
+	}
+
+	/* add a default entry in case the URL does not yet exist */
+	private static void setDefault(Boolean force, String name, String url)
+	{
+		String testurl = url.replaceAll("=", "_");
+		wmsListDefault.put(name, url);
+
+		if(force && !Main.pref.getBoolean("wmsplugin.default."+testurl))
+		{
+			Main.pref.put("wmsplugin.default."+testurl, true);
+			int id = -1;
+			for(WMSInfo i : wmsList)
+			{
+				if(url.equals(i.url))
+					return;
+				if(i.prefid > id)
+					id = i.prefid;
+			}
+			WMSInfo newinfo = new WMSInfo(name, url, id+1);
+			newinfo.save();
+			wmsList.add(newinfo);
+		}
+	}
+
+	public static Grabber getGrabber(ProjectionBounds bounds, GeorefImage img, MapView mv, WMSLayer layer){
+		if(layer.baseURL.startsWith("html:"))
+			return new HTMLGrabber(bounds, img, mv, layer, cache);
+		else
+			return new WMSGrabber(bounds, img, mv, layer, cache);
+	}
+
+	private static void setEnabledAll(boolean isEnabled) {
+		for(int i=0; i < wmsJMenu.getItemCount(); i++) {
+			JMenuItem item = wmsJMenu.getItem(i);
+
+			if(item != null) item.setEnabled(isEnabled);
+		}
+		menuEnabled = isEnabled;
+	}
+
+	@Override
+	public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+		if (oldFrame==null && newFrame!=null) {
+			setEnabledAll(true);
+			Main.map.addMapMode(new IconToggleButton
+					(new WMSAdjustAction(Main.map)));
+		} else if (oldFrame!=null && newFrame==null ) {
+			setEnabledAll(false);
+		}
+	}
+
+	@Override
+	public PreferenceSetting getPreferenceSetting() {
+		return new WMSPreferenceEditor();
+	}
+
+	static public String getPrefsPath()
+	{
+		return Main.pref.getPluginsDirectory().getPath() + "/wmsplugin/";
+	}
 }
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java	(revision 22676)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSPreferenceEditor.java	(revision 22677)
@@ -32,251 +32,265 @@
 
 public class WMSPreferenceEditor implements PreferenceSetting {
-    private DefaultTableModel model;
-    private JComboBox browser;
-    private HashMap<Integer, WMSInfo> oldValues = new HashMap<Integer, WMSInfo>();
-
-    JCheckBox overlapCheckBox;
-    JSpinner spinEast;
-    JSpinner spinNorth;
-    JSpinner spinSimConn;
-
-    public void addGui(final PreferenceTabbedPane gui) {
-        JPanel p = gui.createPreferenceTab("wms", tr("WMS Plugin Preferences"), tr("Modify list of WMS servers displayed in the WMS plugin menu"));
-
-        model = new DefaultTableModel(new String[]{tr("Menu Name"), tr("WMS URL")}, 0);
-        final JTable list = new JTable(model);
-        JScrollPane scroll = new JScrollPane(list);
-        p.add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
-        scroll.setPreferredSize(new Dimension(200,200));
-
-        for (WMSInfo i : WMSPlugin.wmsList) {
-            oldValues.put(i.prefid, i);
-            model.addRow(new String[]{i.name, i.url});
-        }
-
-        final DefaultTableModel modeldef = new DefaultTableModel(
-        new String[]{tr("Menu Name (Default)"), tr("WMS URL (Default)")}, 0);
-        final JTable listdef = new JTable(modeldef){
-            @Override
-            public boolean isCellEditable(int row,int column){return false;}
-        };
-        JScrollPane scrolldef = new JScrollPane(listdef);
-        // scrolldef is added after the buttons so it's clearer the buttons
-        // control the top list and not the default one
-        scrolldef.setPreferredSize(new Dimension(200,200));
-
-        for (Map.Entry<String,String> i : WMSPlugin.wmsListDefault.entrySet()) {
-            modeldef.addRow(new String[]{i.getKey(), i.getValue()});
-        }
-
-        JPanel buttonPanel = new JPanel(new FlowLayout());
-
-        JButton add = new JButton(tr("Add"));
-        buttonPanel.add(add, GBC.std().insets(0,5,0,0));
-        add.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                JPanel p = new JPanel(new GridBagLayout());
-                p.add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
-                JTextField key = new JTextField(40);
-                JTextField value = new JTextField(40);
-                p.add(key, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
-                p.add(new JLabel(tr("WMS URL")), GBC.std().insets(0,0,5,0));
-                p.add(value, GBC.eol().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
-                int answer = JOptionPane.showConfirmDialog(
-                        gui, p,
-                        tr("Enter a menu name and WMS URL"),
-                        JOptionPane.OK_CANCEL_OPTION,
-                        JOptionPane.QUESTION_MESSAGE);
-                if (answer == JOptionPane.OK_OPTION) {
-                    model.addRow(new String[]{key.getText(), value.getText()});
-                }
-            }
-        });
-
-        JButton delete = new JButton(tr("Delete"));
-        buttonPanel.add(delete, GBC.std().insets(0,5,0,0));
-        delete.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                if (list.getSelectedRow() == -1)
-                    JOptionPane.showMessageDialog(gui, tr("Please select the row to delete."));
-                else
-                {
-                    Integer i;
-                    while ((i = list.getSelectedRow()) != -1)
-                        model.removeRow(i);
-                }
-            }
-        });
-
-        JButton copy = new JButton(tr("Copy Selected Default(s)"));
-        buttonPanel.add(copy, GBC.std().insets(0,5,0,0));
-        copy.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                int[] lines = listdef.getSelectedRows();
-                if (lines.length == 0) {
-                    JOptionPane.showMessageDialog(
-                            gui,
-                            tr("Please select at least one row to copy."),
-                            tr("Information"),
-                            JOptionPane.INFORMATION_MESSAGE
-                            );
-                    return;
-                }
-
-                outer: for(int i = 0; i < lines.length; i++) {
-                    String c1 = modeldef.getValueAt(lines[i], 0).toString();
-                    String c2 = modeldef.getValueAt(lines[i], 1).toString();
-
-                    // Check if an entry with exactly the same values already
-                    // exists
-                    for(int j = 0; j < model.getRowCount(); j++) {
-                        if(c1.equals(model.getValueAt(j, 0).toString())
-                                && c2.equals(model.getValueAt(j, 1).toString())) {
-                            // Select the already existing row so the user has
-                            // some feedback in case an entry exists
-                            list.getSelectionModel().setSelectionInterval(j, j);
-                            list.scrollRectToVisible(list.getCellRect(j, 0, true));
-                            continue outer;
-                        }
-                    }
-
-                    model.addRow(new String[] {c1, c2});
-                    int lastLine = model.getRowCount() - 1;
-                    list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
-                    list.scrollRectToVisible(list.getCellRect(lastLine, 0, true));
-                }
-            }
-        });
-
-        p.add(buttonPanel);
-        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-        // Add default item list
-        p.add(scrolldef, GBC.eol().insets(0,5,0,0).fill(GridBagConstraints.BOTH));
-
-        browser = new JComboBox(new String[]{
-        "webkit-image {0}",
-        "gnome-web-photo --mode=photo --format=png {0} /dev/stdout",
-        "gnome-web-photo-fixed {0}",
-        "webkit-image-gtk {0}"});
-        browser.setEditable(true);
-        browser.setSelectedItem(Main.pref.get("wmsplugin.browser", "webkit-image {0}"));
-        p.add(new JLabel(tr("Downloader:")), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-        p.add(browser);
-
-        //Overlap
-        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-
-        overlapCheckBox = new JCheckBox(tr("Overlap tiles"), WMSPlugin.doOverlap );
-        JLabel labelEast = new JLabel(tr("% of east:"));
-        JLabel labelNorth = new JLabel(tr("% of north:"));
-        spinEast = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapEast, 1, 50, 1));
-        spinNorth = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapNorth, 1, 50, 1));
-
-        JPanel overlapPanel = new JPanel(new FlowLayout());
-        overlapPanel.add(overlapCheckBox);
-        overlapPanel.add(labelEast);
-        overlapPanel.add(spinEast);
-        overlapPanel.add(labelNorth);
-        overlapPanel.add(spinNorth);
-
-        p.add(overlapPanel);
-               
-        // Simultaneous connections
-        p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-        JLabel labelSimConn = new JLabel(tr("Simultaneous connections"));
-        spinSimConn = new JSpinner(new SpinnerNumberModel(WMSPlugin.simultaneousConnections, 1, 30, 1));
-        JPanel overlapPanelSimConn = new JPanel(new FlowLayout());
-        overlapPanelSimConn.add(labelSimConn);
-        overlapPanelSimConn.add(spinSimConn);
-        p.add(overlapPanelSimConn);
-    }
-
-    public boolean ok() {
-        boolean change = false;
-        for (int i = 0; i < model.getRowCount(); ++i) {
-            String name = model.getValueAt(i,0).toString();
-            String url = model.getValueAt(i,1).toString();
-
-            WMSInfo origValue = oldValues.get(i);
-            if (origValue == null)
-            {
-                new WMSInfo(name, url, i).save();
-                change = true;
-            }
-            else
-            {
-                if (!origValue.name.equals(name) || !origValue.url.equals(url))
-                {
-                    origValue.name = name;
-                    origValue.url = url;
-                    origValue.save();
-                    change = true;
-                }
-                oldValues.remove(i);
-            }
-        }
-
-        // using null values instead of empty string really deletes
-        // the preferences entry
-        for (WMSInfo i : oldValues.values())
-        {
-            i.url = null;
-            i.name = null;
-            i.save();
-            change = true;
-        }
-
-        if (change) WMSPlugin.refreshMenu();
-
-        WMSPlugin.doOverlap = overlapCheckBox.getModel().isSelected();
-        WMSPlugin.overlapEast = (Integer) spinEast.getModel().getValue();
-        WMSPlugin.overlapNorth = (Integer) spinNorth.getModel().getValue();
-        WMSPlugin.simultaneousConnections = (Integer) spinSimConn.getModel().getValue();
-
-        Main.pref.put("wmsplugin.url.overlap",    String.valueOf(WMSPlugin.doOverlap));
-        Main.pref.put("wmsplugin.url.overlapEast", String.valueOf(WMSPlugin.overlapEast));
-        Main.pref.put("wmsplugin.url.overlapNorth", String.valueOf(WMSPlugin.overlapNorth));
-
-        Main.pref.put("wmsplugin.browser", browser.getEditor().getItem().toString()); 
-        Main.pref.put("wmsplugin.simultaneousConnections", String.valueOf(WMSPlugin.simultaneousConnections));
-        return false;
-    }
-
-    /**
-     * Updates a server URL in the preferences dialog. Used by other plugins.
-     *
-     * @param server The server name
-     * @param url The server URL
-     */
-    public void setServerUrl(String server, String url)
-    {
-        for (int i = 0; i < model.getRowCount(); i++)
-        {
-            if( server.equals(model.getValueAt(i,0).toString()) )
-            {
-                model.setValueAt(url, i, 1);
-                return;
-            }
-        }
-        model.addRow(new String[]{server, url});
-    }
-
-    /**
-     * Gets a server URL in the preferences dialog. Used by other plugins.
-     *
-     * @param server The server name
-     * @return The server URL
-     */
-    public String getServerUrl(String server)
-    {
-        for (int i = 0; i < model.getRowCount(); i++)
-        {
-            if( server.equals(model.getValueAt(i,0).toString()) )
-            {
-                return model.getValueAt(i,1).toString();
-            }
-        }
-        return null;
-    }
+	private DefaultTableModel model;
+	private JComboBox browser;
+	private HashMap<Integer, WMSInfo> oldValues = new HashMap<Integer, WMSInfo>();
+
+	JCheckBox overlapCheckBox;
+	JSpinner spinEast;
+	JSpinner spinNorth;
+	JSpinner spinSimConn;
+	JCheckBox remoteCheckBox;
+	boolean allowRemoteControl = true;
+
+	public void addGui(final PreferenceTabbedPane gui) {
+		JPanel p = gui.createPreferenceTab("wms", tr("WMS Plugin Preferences"), tr("Modify list of WMS servers displayed in the WMS plugin menu"));
+
+		model = new DefaultTableModel(new String[]{tr("Menu Name"), tr("WMS URL")}, 0);
+		final JTable list = new JTable(model);
+		JScrollPane scroll = new JScrollPane(list);
+		p.add(scroll, GBC.eol().fill(GridBagConstraints.BOTH));
+		scroll.setPreferredSize(new Dimension(200,200));
+
+		for (WMSInfo i : WMSPlugin.wmsList) {
+			oldValues.put(i.prefid, i);
+			model.addRow(new String[]{i.name, i.url});
+		}
+
+		final DefaultTableModel modeldef = new DefaultTableModel(
+				new String[]{tr("Menu Name (Default)"), tr("WMS URL (Default)")}, 0);
+		final JTable listdef = new JTable(modeldef){
+			@Override
+			public boolean isCellEditable(int row,int column){return false;}
+		};
+		JScrollPane scrolldef = new JScrollPane(listdef);
+		// scrolldef is added after the buttons so it's clearer the buttons
+		// control the top list and not the default one
+		scrolldef.setPreferredSize(new Dimension(200,200));
+
+		for (Map.Entry<String,String> i : WMSPlugin.wmsListDefault.entrySet()) {
+			modeldef.addRow(new String[]{i.getKey(), i.getValue()});
+		}
+
+		JPanel buttonPanel = new JPanel(new FlowLayout());
+
+		JButton add = new JButton(tr("Add"));
+		buttonPanel.add(add, GBC.std().insets(0,5,0,0));
+		add.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				JPanel p = new JPanel(new GridBagLayout());
+				p.add(new JLabel(tr("Menu Name")), GBC.std().insets(0,0,5,0));
+				JTextField key = new JTextField(40);
+				JTextField value = new JTextField(40);
+				p.add(key, GBC.eop().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
+				p.add(new JLabel(tr("WMS URL")), GBC.std().insets(0,0,5,0));
+				p.add(value, GBC.eol().insets(5,0,0,0).fill(GridBagConstraints.HORIZONTAL));
+				int answer = JOptionPane.showConfirmDialog(
+						gui, p,
+						tr("Enter a menu name and WMS URL"),
+						JOptionPane.OK_CANCEL_OPTION,
+						JOptionPane.QUESTION_MESSAGE);
+				if (answer == JOptionPane.OK_OPTION) {
+					model.addRow(new String[]{key.getText(), value.getText()});
+				}
+			}
+		});
+
+		JButton delete = new JButton(tr("Delete"));
+		buttonPanel.add(delete, GBC.std().insets(0,5,0,0));
+		delete.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				if (list.getSelectedRow() == -1)
+					JOptionPane.showMessageDialog(gui, tr("Please select the row to delete."));
+				else
+				{
+					Integer i;
+					while ((i = list.getSelectedRow()) != -1)
+						model.removeRow(i);
+				}
+			}
+		});
+
+		JButton copy = new JButton(tr("Copy Selected Default(s)"));
+		buttonPanel.add(copy, GBC.std().insets(0,5,0,0));
+		copy.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+				int[] lines = listdef.getSelectedRows();
+				if (lines.length == 0) {
+					JOptionPane.showMessageDialog(
+							gui,
+							tr("Please select at least one row to copy."),
+							tr("Information"),
+							JOptionPane.INFORMATION_MESSAGE
+					);
+					return;
+				}
+
+				outer: for(int i = 0; i < lines.length; i++) {
+					String c1 = modeldef.getValueAt(lines[i], 0).toString();
+					String c2 = modeldef.getValueAt(lines[i], 1).toString();
+
+					// Check if an entry with exactly the same values already
+					// exists
+					for(int j = 0; j < model.getRowCount(); j++) {
+						if(c1.equals(model.getValueAt(j, 0).toString())
+								&& c2.equals(model.getValueAt(j, 1).toString())) {
+							// Select the already existing row so the user has
+							// some feedback in case an entry exists
+							list.getSelectionModel().setSelectionInterval(j, j);
+							list.scrollRectToVisible(list.getCellRect(j, 0, true));
+							continue outer;
+						}
+					}
+
+					model.addRow(new String[] {c1, c2});
+					int lastLine = model.getRowCount() - 1;
+					list.getSelectionModel().setSelectionInterval(lastLine, lastLine);
+					list.scrollRectToVisible(list.getCellRect(lastLine, 0, true));
+				}
+			}
+		});
+
+		p.add(buttonPanel);
+		p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+		// Add default item list
+		p.add(scrolldef, GBC.eol().insets(0,5,0,0).fill(GridBagConstraints.BOTH));
+
+		browser = new JComboBox(new String[]{
+				"webkit-image {0}",
+				"gnome-web-photo --mode=photo --format=png {0} /dev/stdout",
+				"gnome-web-photo-fixed {0}",
+		"webkit-image-gtk {0}"});
+		browser.setEditable(true);
+		browser.setSelectedItem(Main.pref.get("wmsplugin.browser", "webkit-image {0}"));
+		p.add(new JLabel(tr("Downloader:")), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+		p.add(browser);
+
+		//Overlap
+		p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+
+		overlapCheckBox = new JCheckBox(tr("Overlap tiles"), WMSPlugin.doOverlap );
+		JLabel labelEast = new JLabel(tr("% of east:"));
+		JLabel labelNorth = new JLabel(tr("% of north:"));
+		spinEast = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapEast, 1, 50, 1));
+		spinNorth = new JSpinner(new SpinnerNumberModel(WMSPlugin.overlapNorth, 1, 50, 1));
+
+		JPanel overlapPanel = new JPanel(new FlowLayout());
+		overlapPanel.add(overlapCheckBox);
+		overlapPanel.add(labelEast);
+		overlapPanel.add(spinEast);
+		overlapPanel.add(labelNorth);
+		overlapPanel.add(spinNorth);
+
+		p.add(overlapPanel);
+
+		// Simultaneous connections
+		p.add(Box.createHorizontalGlue(), GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+		JLabel labelSimConn = new JLabel(tr("Simultaneous connections"));
+		spinSimConn = new JSpinner(new SpinnerNumberModel(WMSPlugin.simultaneousConnections, 1, 30, 1));
+		JPanel overlapPanelSimConn = new JPanel(new FlowLayout());
+		overlapPanelSimConn.add(labelSimConn);
+		overlapPanelSimConn.add(spinSimConn);
+		p.add(overlapPanelSimConn, GBC.eol().fill(GridBagConstraints.HORIZONTAL));
+
+
+		allowRemoteControl = Main.pref.getBoolean("wmsplugin.remotecontrol", true);
+		remoteCheckBox = new JCheckBox(tr("Allow remote control (reqires remotecontrol plugin)"), allowRemoteControl );
+		JPanel remotePanel = new JPanel(new FlowLayout());
+		remotePanel.add(remoteCheckBox);
+
+		p.add(remotePanel);
+
+	}
+
+	public boolean ok() {
+		boolean change = false;
+		for (int i = 0; i < model.getRowCount(); ++i) {
+			String name = model.getValueAt(i,0).toString();
+			String url = model.getValueAt(i,1).toString();
+
+			WMSInfo origValue = oldValues.get(i);
+			if (origValue == null)
+			{
+				new WMSInfo(name, url, i).save();
+				change = true;
+			}
+			else
+			{
+				if (!origValue.name.equals(name) || !origValue.url.equals(url))
+				{
+					origValue.name = name;
+					origValue.url = url;
+					origValue.save();
+					change = true;
+				}
+				oldValues.remove(i);
+			}
+		}
+
+		// using null values instead of empty string really deletes
+		// the preferences entry
+		for (WMSInfo i : oldValues.values())
+		{
+			i.url = null;
+			i.name = null;
+			i.save();
+			change = true;
+		}
+
+		if (change) WMSPlugin.refreshMenu();
+
+		WMSPlugin.doOverlap = overlapCheckBox.getModel().isSelected();
+		WMSPlugin.overlapEast = (Integer) spinEast.getModel().getValue();
+		WMSPlugin.overlapNorth = (Integer) spinNorth.getModel().getValue();
+		WMSPlugin.simultaneousConnections = (Integer) spinSimConn.getModel().getValue();
+		allowRemoteControl = remoteCheckBox.getModel().isSelected();
+
+		Main.pref.put("wmsplugin.url.overlap",    String.valueOf(WMSPlugin.doOverlap));
+		Main.pref.put("wmsplugin.url.overlapEast", String.valueOf(WMSPlugin.overlapEast));
+		Main.pref.put("wmsplugin.url.overlapNorth", String.valueOf(WMSPlugin.overlapNorth));
+
+		Main.pref.put("wmsplugin.browser", browser.getEditor().getItem().toString());
+		Main.pref.put("wmsplugin.simultaneousConnections", String.valueOf(WMSPlugin.simultaneousConnections));
+
+		Main.pref.put("wmsplugin.remotecontrol",    String.valueOf(allowRemoteControl));
+		return false;
+	}
+
+	/**
+	 * Updates a server URL in the preferences dialog. Used by other plugins.
+	 *
+	 * @param server The server name
+	 * @param url The server URL
+	 */
+	public void setServerUrl(String server, String url)
+	{
+		for (int i = 0; i < model.getRowCount(); i++)
+		{
+			if( server.equals(model.getValueAt(i,0).toString()) )
+			{
+				model.setValueAt(url, i, 1);
+				return;
+			}
+		}
+		model.addRow(new String[]{server, url});
+	}
+
+	/**
+	 * Gets a server URL in the preferences dialog. Used by other plugins.
+	 *
+	 * @param server The server name
+	 * @return The server URL
+	 */
+	public String getServerUrl(String server)
+	{
+		for (int i = 0; i < model.getRowCount(); i++)
+		{
+			if( server.equals(model.getValueAt(i,0).toString()) )
+			{
+				return model.getValueAt(i,1).toString();
+			}
+		}
+		return null;
+	}
 }
 
Index: /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSRemoteHandler.java
===================================================================
--- /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSRemoteHandler.java	(revision 22677)
+++ /applications/editors/josm/plugins/wmsplugin/src/wmsplugin/WMSRemoteHandler.java	(revision 22677)
@@ -0,0 +1,108 @@
+package wmsplugin;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.plugins.remotecontrol.PermissionPref;
+import org.openstreetmap.josm.plugins.remotecontrol.RequestHandler;
+import org.openstreetmap.josm.plugins.remotecontrol.RequestHandlerErrorException;
+
+public class WMSRemoteHandler extends RequestHandler {
+
+	public static final String command = "/wms";
+
+	@Override
+	public String getPermissionMessage() {
+		return tr("Remote Control has been asked to load a WMS layer from the following URL:") +
+		"<br>" + args.get("url");
+	}
+
+	@Override
+	public PermissionPref getPermissionPref()
+	{
+		return new PermissionPref("wmsplugin.remotecontrol",
+		"RemoteControl: WMS forbidden by preferences");
+	}
+
+	@Override
+	protected String[] getMandatoryParams()
+	{
+		return new String[] { "url" };
+	}
+
+	@Override
+	protected void handleRequest() throws RequestHandlerErrorException {
+		String url = args.get("url");
+		String title = args.get("title");
+		if((title == null) || (title.length() == 0))
+		{
+			title = "remote WMS";
+		}
+		String cookies = args.get("cookies");
+		if(cookies == null)
+		{
+			cookies = "";
+		}
+		WMSLayer wmsLayer = new WMSLayer(title, url, cookies);
+		Main.main.addLayer(wmsLayer);
+
+	}
+
+	@Override
+	public void parseArgs() {
+		StringTokenizer st = new StringTokenizer(request, "&?");
+		HashMap<String, String> args = new HashMap<String, String>();
+		// skip first element which is the command
+		if(st.hasMoreTokens()) st.nextToken();
+		while (st.hasMoreTokens()) {
+			String param = st.nextToken();
+			int eq = param.indexOf("=");
+			if (eq > -1)
+			{
+				String key = param.substring(0, eq);
+				/* "url=" terminates normal parameters
+				 * and will be handled separately
+				 */
+				if("url".equals(key)) break;
+
+				String value = param.substring(eq + 1);
+				// urldecode all normal values
+				try {
+					value = URLDecoder.decode(value, "UTF-8");
+				} catch (UnsupportedEncodingException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+				args.put(key,
+						value);
+			}
+		}
+		// url as second or later parameter
+		int urlpos = request.indexOf("&url=");
+		// url as first (and only) parameter
+		if(urlpos < 0) urlpos = request.indexOf("?url=");
+		// url found?
+		if(urlpos >= 0) {
+			// URL value
+			String value = request.substring(urlpos + 5);
+			// allow skipping URL decoding with urldecode=false
+			String urldecode = args.get("urldecode");
+			if((urldecode == null) || (Boolean.valueOf(urldecode) == true))
+			{
+				try {
+					value = URLDecoder.decode(value, "UTF-8");
+				} catch (UnsupportedEncodingException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			}
+			args.put("url", value);
+		}
+		this.args = args;
+	}
+}
