Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 5278)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 5279)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.data.validation.OsmValidator;
 import org.openstreetmap.josm.gui.GettingStarted;
+import org.openstreetmap.josm.gui.MainApplication.Option;
 import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
@@ -474,5 +475,5 @@
      * @param args The parsed argument list.
      */
-    public static void preConstructorInit(Map<String, Collection<String>> args) {
+    public static void preConstructorInit(Map<Option, Collection<String>> args) {
         ProjectionPreference.setProjection();
 
@@ -514,12 +515,12 @@
 
         geometry = WindowGeometry.mainWindow("gui.geometry",
-            (args.containsKey("geometry") ? args.get("geometry").iterator().next() : null),
-            !args.containsKey("no-maximize") && Main.pref.getBoolean("gui.maximized", false));
-    }
-
-    public void postConstructorProcessCmdLine(Map<String, Collection<String>> args) {
-        if (args.containsKey("download")) {
+            (args.containsKey(Option.GEOMETRY) ? args.get(Option.GEOMETRY).iterator().next() : null),
+            !args.containsKey(Option.NO_MAXIMIZE) && Main.pref.getBoolean("gui.maximized", false));
+    }
+
+    public void postConstructorProcessCmdLine(Map<Option, Collection<String>> args) {
+        if (args.containsKey(Option.DOWNLOAD)) {
             List<File> fileList = new ArrayList<File>();
-            for (String s : args.get("download")) {
+            for (String s : args.get(Option.DOWNLOAD)) {
                 File f = null;
                 switch(paramType(s)) {
@@ -556,6 +557,6 @@
             }
         }
-        if (args.containsKey("downloadgps")) {
-            for (String s : args.get("downloadgps")) {
+        if (args.containsKey(Option.DOWNLOADGPS)) {
+            for (String s : args.get(Option.DOWNLOADGPS)) {
                 switch(paramType(s)) {
                 case httpUrl:
@@ -576,6 +577,6 @@
             }
         }
-        if (args.containsKey("selection")) {
-            for (String s : args.get("selection")) {
+        if (args.containsKey(Option.SELECTION)) {
+            for (String s : args.get(Option.SELECTION)) {
                 SearchAction.search(s, SearchAction.SearchMode.add);
             }
Index: trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 5278)
+++ trunk/src/org/openstreetmap/josm/data/projection/CustomProjection.java	(revision 5279)
@@ -5,10 +5,7 @@
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -340,5 +337,5 @@
     }
 
-    public Bounds parseBounds(String boundsStr) throws ProjectionConfigurationException {
+    public static Bounds parseBounds(String boundsStr) throws ProjectionConfigurationException {
         String[] numStr = boundsStr.split(",");
         if (numStr.length != 4)
@@ -350,5 +347,5 @@
     }
 
-    public double parseDouble(Map<String, String> parameters, String parameterName) throws ProjectionConfigurationException {
+    public static double parseDouble(Map<String, String> parameters, String parameterName) throws ProjectionConfigurationException {
         String doubleStr = parameters.get(parameterName);
         if (doubleStr == null && parameters.containsKey(parameterName))
@@ -358,5 +355,5 @@
     }
 
-    public double parseDouble(String doubleStr, String parameterName) throws ProjectionConfigurationException {
+    public static double parseDouble(String doubleStr, String parameterName) throws ProjectionConfigurationException {
         try {
             return Double.parseDouble(doubleStr);
@@ -367,5 +364,5 @@
     }
 
-    public double parseAngle(String angleStr, String parameterName) throws ProjectionConfigurationException {
+    public static double parseAngle(String angleStr, String parameterName) throws ProjectionConfigurationException {
         String s = angleStr;
         double value = 0;
Index: trunk/src/org/openstreetmap/josm/gui/MainApplet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplet.java	(revision 5278)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplet.java	(revision 5279)
@@ -28,4 +28,5 @@
 import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.data.ServerSidePreferences;
+import org.openstreetmap.josm.gui.MainApplication.Option;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.I18n;
@@ -127,9 +128,9 @@
         }
 
-        Main.preConstructorInit(args);
+        Main.preConstructorInit(Option.fromStringMap(args));
         Main.parent = frame;
         Main.addListener();
 
-        new MainCaller().postConstructorProcessCmdLine(args);
+        new MainCaller().postConstructorProcessCmdLine(Option.fromStringMap(args));
 
         MainMenu m = Main.main.menu; // shortcut
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 5278)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 5279)
@@ -7,5 +7,4 @@
 import java.awt.Image;
 import java.awt.Toolkit;
-import java.awt.event.ActionEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
@@ -19,4 +18,5 @@
 import java.security.Permissions;
 import java.security.Policy;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -28,4 +28,7 @@
 import javax.swing.RepaintManager;
 import javax.swing.SwingUtilities;
+
+import gnu.getopt.Getopt;
+import gnu.getopt.LongOpt;
 
 import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager;
@@ -95,5 +98,5 @@
                 "\tjava -jar josm.jar <options>...\n\n"+
                 tr("options")+":\n"+
-                "\t--help|-?|-h                              "+tr("Show this help")+"\n"+
+                "\t--help|-h                                 "+tr("Show this help")+"\n"+
                 "\t--geometry=widthxheight(+|-)x(+|-)y       "+tr("Standard unix geometry argument")+"\n"+
                 "\t[--download=]minlat,minlon,maxlat,maxlon  "+tr("Download the bounding box")+"\n"+
@@ -125,26 +128,91 @@
     }
 
-    private static Map<String, Collection<String>> buildCommandLineArgumentMap(String[] args) {
-        Map<String, Collection<String>> argMap = new HashMap<String, Collection<String>>();
-        for (String arg : args) {
-            if ("-h".equals(arg) || "-?".equals(arg)) {
-                arg = "--help";
-            } else if ("-v".equals(arg)) {
-                arg = "--version";
-            }
-            // handle simple arguments like file names, URLs, bounds
-            if (!arg.startsWith("--")) {
-                arg = "--download="+arg;
-            }
-            int i = arg.indexOf('=');
-            String key = i == -1 ? arg.substring(2) : arg.substring(2,i);
-            String value = i == -1 ? "" : arg.substring(i+1);
-            Collection<String> v = argMap.get(key);
-            if (v == null) {
-                v = new LinkedList<String>();
-            }
-            v.add(value);
-            argMap.put(key, v);
-        }
+    public enum Option {
+        HELP(false),
+        VERSION(false),
+        LANGUAGE(true),
+        RESET_PREFERENCES(false),
+        LOAD_PREFERENCES(true),
+        SET(true),
+        GEOMETRY(true),
+        NO_MAXIMIZE(false),
+        MAXIMIZE(false),
+        DOWNLOAD(true),
+        DOWNLOADGPS(true),
+        SELECTION(true);
+
+        private String name;
+        private boolean requiresArgument;
+
+        private Option(boolean requiresArgument) {
+            this.name = name().toLowerCase().replace("_", "-");
+            this.requiresArgument = requiresArgument;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean requiresArgument() {
+            return requiresArgument;
+        }
+
+        public static Map<Option, Collection<String>> fromStringMap(Map<String, Collection<String>> opts) {
+            Map<Option, Collection<String>> res = new HashMap<Option, Collection<String>>();
+            for (Map.Entry<String, Collection<String>> e : opts.entrySet()) {
+                Option o = Option.valueOf(e.getKey().toUpperCase().replace("-", "_"));
+                if (o != null) {
+                    res.put(o, e.getValue());
+                }
+            }
+            return res;
+        }
+    }
+
+    private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
+
+        List<LongOpt> los = new ArrayList<LongOpt>();
+        for (Option o : Option.values()) {
+            los.add(new LongOpt(o.getName(), o.requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0));
+        }
+
+        Getopt g = new Getopt("JOSM", args, "hv", los.toArray(new LongOpt[0]));
+
+        Map<Option, Collection<String>> argMap = new HashMap<Option, Collection<String>>();
+
+        int c;
+        while ((c = g.getopt()) != -1 ) {
+            Option opt = null;
+            switch (c) {
+                case 'h':
+                    opt = Option.HELP;
+                    break;
+                case 'v':
+                    opt = Option.VERSION;
+                    break;
+                case 0:
+                    opt = Option.values()[g.getLongind()];
+                    break;
+            }
+            if (opt != null) {
+                Collection<String> values = argMap.get(opt);
+                if (values == null) {
+                    values = new ArrayList<String>();
+                    argMap.put(opt, values);
+                }
+                values.add(g.getOptarg());
+            } else
+                throw new IllegalArgumentException();
+        }
+        // positional arguments are a shortcut for the --download ... option
+        for (int i = g.getOptind(); i < args.length; ++i) {
+            Collection<String> values = argMap.get(Option.DOWNLOAD);
+            if (values == null) {
+                values = new ArrayList<String>();
+                argMap.put(Option.DOWNLOAD, values);
+            }
+            values.add(args[i]);
+        }
+
         return argMap;
     }
@@ -186,7 +254,12 @@
 
         // construct argument table
-        final Map<String, Collection<String>> args = buildCommandLineArgumentMap(argArray);
-
-        if (args.containsKey("version")) {
+        Map<Option, Collection<String>> args = null;
+        try {
+            args = buildCommandLineArgumentMap(argArray);
+        } catch (IllegalArgumentException e) {
+            System.exit(1);
+        }
+
+        if (args.containsKey(Option.VERSION)) {
             System.out.println(Version.getInstance().getAgentString());
             System.exit(0);
@@ -195,9 +268,9 @@
         }
 
-        Main.pref.init(args.containsKey("reset-preferences"));
+        Main.pref.init(args.containsKey(Option.RESET_PREFERENCES));
 
         // Check if passed as parameter
-        if (args.containsKey("language")) {
-            I18n.set(args.get("language").iterator().next());
+        if (args.containsKey(Option.LANGUAGE)) {
+            I18n.set(args.get(Option.LANGUAGE).iterator().next());
         } else {
             I18n.set(Main.pref.get("language", null));
@@ -208,7 +281,7 @@
         Main.parent = mainFrame;
 
-        if (args.containsKey("load-preferences")) {
+        if (args.containsKey(Option.LOAD_PREFERENCES)) {
             CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref);
-            for (String i : args.get("load-preferences")) {
+            for (String i : args.get(Option.LOAD_PREFERENCES)) {
                 System.out.println("Reading preferences from " + i);
                 try {
@@ -221,6 +294,6 @@
         }
 
-        if (args.containsKey("set")) {
-            for (String i : args.get("set")) {
+        if (args.containsKey(Option.SET)) {
+            for (String i : args.get(Option.SET)) {
                 String[] kv = i.split("=", 2);
                 Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]);
@@ -234,5 +307,5 @@
 
         // asking for help? show help and exit
-        if (args.containsKey("help")) {
+        if (args.containsKey(Option.HELP)) {
             showHelp();
             System.exit(0);
@@ -278,5 +351,5 @@
 
         boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized"));
-        if ((!args.containsKey("no-maximize") && maximized) || args.containsKey("maximize")) {
+        if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) {
             if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
                 // Main.debug("Main window maximized");
@@ -292,4 +365,6 @@
             main.menu.fullscreenToggleAction.initial();
         }
+
+        final Map<Option, Collection<String>> args_final = args;
 
         SwingUtilities.invokeLater(new Runnable() {
@@ -319,5 +394,5 @@
                 }
 
-                main.postConstructorProcessCmdLine(args);
+                main.postConstructorProcessCmdLine(args_final);
 
                 DownloadDialog.autostartIfNeeded();
