Index: trunk/src/org/openstreetmap/josm/actions/StopChangesetAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/StopChangesetAction.java	(revision 2058)
+++ trunk/src/org/openstreetmap/josm/actions/StopChangesetAction.java	(revision 2061)
@@ -28,6 +28,6 @@
                         "system:closechangeset",
                         tr("File: {0}", tr("Close the current changeset ...")),
-                        KeyEvent.VK_O,
-                        Shortcut.GROUP_MENU
+                        KeyEvent.VK_Q,
+                        Shortcut.GROUP_HOTKEY + Shortcut.GROUPS_ALT2
                 ),
                 true
Index: trunk/src/org/openstreetmap/josm/actions/UploadAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 2058)
+++ trunk/src/org/openstreetmap/josm/actions/UploadAction.java	(revision 2061)
@@ -3,4 +3,5 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
 
 import java.awt.BorderLayout;
@@ -245,11 +246,11 @@
         );
         switch(ret) {
-            case JOptionPane.CLOSED_OPTION: return;
-            case JOptionPane.CANCEL_OPTION: return;
-            case 0: synchronizePrimitive(id); break;
-            case 1: synchronizeDataSet(); break;
-            default:
-                // should not happen
-                throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
+        case JOptionPane.CLOSED_OPTION: return;
+        case JOptionPane.CANCEL_OPTION: return;
+        case 0: synchronizePrimitive(id); break;
+        case 1: synchronizeDataSet(); break;
+        default:
+            // should not happen
+            throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
         }
     }
@@ -285,10 +286,10 @@
         );
         switch(ret) {
-            case JOptionPane.CLOSED_OPTION: return;
-            case 1: return;
-            case 0: synchronizeDataSet(); break;
-            default:
-                // should not happen
-                throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
+        case JOptionPane.CLOSED_OPTION: return;
+        case 1: return;
+        case 0: synchronizeDataSet(); break;
+        default:
+            // should not happen
+            throw new IllegalStateException(tr("unexpected return value. Got {0}", ret));
         }
     }
@@ -587,25 +588,51 @@
     static public class UploadDialogPanel extends JPanel {
 
+        /** the list with the added primitives */
         private JList lstAdd;
+        private JLabel lblAdd;
+        private JScrollPane spAdd;
+        /** the list with the updated primitives */
         private JList lstUpdate;
+        private JLabel lblUpdate;
+        private JScrollPane spUpdate;
+        /** the list with the deleted primitives */
         private JList lstDelete;
-        private JLabel lblAdd;
-        private JLabel lblUpdate;
         private JLabel lblDelete;
+        private JScrollPane spDelete;
+        /** the panel containing the widgets for the lists of primitives */
         private JPanel pnlLists;
+        /** checkbox for selecting whether an atomic upload is to be used  */
         private JCheckBox cbUseAtomicUpload;
+        /** input field for changeset comment */
         private SuggestingJHistoryComboBox cmt;
+        /** ui component for editing changeset tags */
         private TagEditorPanel tagEditorPanel;
+        /** the tabbed pane used below of the list of primitives  */
         private JTabbedPane southTabbedPane;
+        /** the button group with the changeset processing types */
         private ButtonGroup bgChangesetHandlingOptions;
+        /** radio buttons for selecting a changeset processing type */
         private Map<ChangesetProcessingType, JRadioButton> rbChangesetHandlingOptions;
 
+        /**
+         * builds the panel with the lists of primitives
+         * 
+         * @return the panel with the lists of primitives
+         */
         protected JPanel buildListsPanel() {
             pnlLists = new JPanel();
             pnlLists.setLayout(new GridBagLayout());
-
+            // we don't add the lists yet, see setUploadPrimivies()
+            //
             return pnlLists;
         }
 
+        /**
+         * builds the panel with the ui components for controlling how the changeset
+         * should be processed (opening/closing a changeset)
+         * 
+         * @return the panel with the ui components for controlling how the changeset
+         * should be processed
+         */
         protected JPanel buildChangesetHandlingControlPanel() {
             JPanel pnl = new JPanel();
@@ -639,4 +666,10 @@
         }
 
+        /**
+         * build the panel with the widgets for controlling how the changeset should be processed
+         * (atomic upload or not, comment, opening/closing changeset)
+         * 
+         * @return
+         */
         protected JPanel buildChangesetControlPanel() {
             JPanel pnl = new JPanel();
@@ -652,4 +685,9 @@
         }
 
+        /**
+         * builds the upload control panel
+         * 
+         * @return
+         */
         protected JPanel buildUploadControlPanel() {
             JPanel pnl = new JPanel();
@@ -667,7 +705,13 @@
         }
 
+        /**
+         * builds the gui
+         */
         protected void build() {
             setLayout(new GridBagLayout());
             GridBagConstraints gc = new GridBagConstraints();
+
+            // first the panel with the list in the upper half
+            //
             gc.fill = GridBagConstraints.BOTH;
             gc.weightx = 1.0;
@@ -675,4 +719,7 @@
             add(buildListsPanel(), gc);
 
+            // a tabbed pane with two configuration panels in the
+            // lower half
+            //
             southTabbedPane = new JTabbedPane();
             southTabbedPane.add(buildUploadControlPanel());
@@ -691,22 +738,42 @@
         }
 
-
+        /**
+         * constructor
+         */
         protected UploadDialogPanel() {
             OsmPrimitivRenderer renderer = new OsmPrimitivRenderer();
 
+            // initialize the three lists for primitives
+            //
             lstAdd = new JList();
             lstAdd.setCellRenderer(renderer);
             lstAdd.setVisibleRowCount(Math.min(lstAdd.getModel().getSize(), 10));
+            spAdd = new JScrollPane(lstAdd);
+            lblAdd = new JLabel(tr("Objects to add:"));
 
             lstUpdate = new JList();
             lstUpdate.setCellRenderer(renderer);
             lstUpdate.setVisibleRowCount(Math.min(lstUpdate.getModel().getSize(), 10));
+            spUpdate = new JScrollPane(lstUpdate);
+            lblUpdate = new JLabel(tr("Objects to modify:"));
 
             lstDelete = new JList();
             lstDelete.setCellRenderer(renderer);
             lstDelete.setVisibleRowCount(Math.min(lstDelete.getModel().getSize(), 10));
+            spDelete = new JScrollPane(lstDelete);
+            lblDelete = new JLabel(tr("Objects to delete:"));
+
+            // build the GUI
+            //
             build();
         }
 
+        /**
+         * sets the collection of primitives which will be uploaded
+         * 
+         * @param add  the collection of primitives to add
+         * @param update the collection of primitives to update
+         * @param delete the collection of primitives to delete
+         */
         public void setUploadedPrimitives(Collection<OsmPrimitive> add, Collection<OsmPrimitive> update, Collection<OsmPrimitive> delete) {
             lstAdd.setListData(add.toArray());
@@ -731,27 +798,35 @@
                 y++;
                 gcLabel.gridy = y;
-                pnlLists.add(lblAdd = new JLabel(tr("Objects to add:")), gcLabel);
+                lblAdd.setText(trn("{0} object to add:", "{0} objects to add:", add.size(),add.size()));
+                pnlLists.add(lblAdd, gcLabel);
                 y++;
                 gcList.gridy = y;
-                pnlLists.add(new JScrollPane(lstAdd), gcList);
+                pnlLists.add(spAdd, gcList);
             }
             if (!update.isEmpty()) {
                 y++;
                 gcLabel.gridy = y;
-                pnlLists.add(lblUpdate = new JLabel(tr("Objects to modify:")), gcLabel);
+                lblUpdate.setText(trn("{0} object to modifiy:", "{0} objects to modify:", update.size(),update.size()));
+                pnlLists.add(lblUpdate, gcLabel);
                 y++;
                 gcList.gridy = y;
-                pnlLists.add(new JScrollPane(lstUpdate), gcList);
+                pnlLists.add(spUpdate, gcList);
             }
             if (!delete.isEmpty()) {
                 y++;
                 gcLabel.gridy = y;
-                pnlLists.add(lblDelete = new JLabel(tr("Objects to delete:")), gcLabel);
+                lblDelete.setText(trn("{0} object to delete:", "{0} objects to delete:", delete.size(),delete.size()));
+                pnlLists.add(lblDelete, gcLabel);
                 y++;
                 gcList.gridy = y;
-                pnlLists.add(new JScrollPane(lstDelete), gcList);
-            }
-        }
-
+                pnlLists.add(spDelete, gcList);
+            }
+        }
+
+        /**
+         * Replies true if a valid changeset comment has been entered in this dialog
+         * 
+         * @return true if a valid changeset comment has been entered in this dialog
+         */
         public boolean hasChangesetComment() {
             if (!getChangesetProcessingType().isUseNew())
@@ -760,4 +835,7 @@
         }
 
+        /**
+         * Remembers the user input in the preference settings
+         */
         public void rememberUserInput() {
             // store the history of comments
@@ -767,4 +845,7 @@
         }
 
+        /**
+         * Initializes the panel for user input
+         */
         public void startUserInput() {
             tagEditorPanel.initAutoCompletion(Main.main.getEditLayer());
@@ -774,4 +855,9 @@
         }
 
+        /**
+         * Replies the current changeset processing type
+         * 
+         * @return the current changeset processing type
+         */
         public ChangesetProcessingType getChangesetProcessingType() {
             ChangesetProcessingType changesetProcessingType = null;
@@ -787,4 +873,9 @@
         }
 
+        /**
+         * Replies the current changeset
+         * 
+         * @return the current changeset
+         */
         public Changeset getChangeset() {
             Changeset changeset = new Changeset();
@@ -794,4 +885,8 @@
         }
 
+        /**
+         * initializes the panel depending on the possible changeset processing
+         * types
+         */
         protected void initChangesetProcessingType() {
             for (ChangesetProcessingType type: ChangesetProcessingType.values()) {
@@ -826,4 +921,28 @@
                 rbChangesetHandlingOptions.get(type).setSelected(true);
             }
+            refreshChangesetProcessingType(getChangesetProcessingType());
+        }
+
+        /**
+         * refreshes  the panel depending on a changeset processing type
+         * 
+         * @param type the changeset processing type
+         */
+        protected void refreshChangesetProcessingType(ChangesetProcessingType type) {
+            if (type.isUseNew()) {
+                southTabbedPane.setTitleAt(1, tr("Tags of new changeset"));
+                Changeset cs = new Changeset();
+                tagEditorPanel.getModel().initFromPrimitive(cs);
+            } else {
+                Changeset cs = OsmApi.getOsmApi().getCurrentChangeset();
+                if (cs != null) {
+                    southTabbedPane.setTitleAt(1, tr("Tags of changeset {0}", cs.getId()));
+                    if (cs.get("comment") != null) {
+                        cmt.setText(cs.get("comment"));
+                        cs.remove("comment");
+                    }
+                    tagEditorPanel.getModel().initFromPrimitive(cs);
+                }
+            }
         }
 
@@ -831,18 +950,5 @@
             public void actionPerformed(ActionEvent e) {
                 ChangesetProcessingType type = getChangesetProcessingType();
-                if (type.isUseNew()) {
-                    tagEditorPanel.setEnabled(true);
-                    southTabbedPane.setTitleAt(1, tr("Tags of new changeset"));
-                    cmt.setEnabled(true);
-                } else {
-                    tagEditorPanel.setEnabled(false);
-                    cmt.setEnabled(false);
-                    Changeset cs = OsmApi.getOsmApi().getCurrentChangeset();
-                    if (cs != null) {
-                        tagEditorPanel.getModel().initFromPrimitive(cs);
-                        southTabbedPane.setTitleAt(1, tr("Tags of changeset {0} (read-only)", cs.getId()));
-                        cmt.setText(cs.get("comment" == null ? "" : cs.get("comment")));
-                    }
-                }
+                refreshChangesetProcessingType(type);
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 2058)
+++ trunk/src/org/openstreetmap/josm/gui/MainMenu.java	(revision 2061)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.actions.ShowStatusReportAction;
 import org.openstreetmap.josm.actions.SplitWayAction;
+import org.openstreetmap.josm.actions.StopChangesetAction;
 import org.openstreetmap.josm.actions.ToggleGPXLinesAction;
 import org.openstreetmap.josm.actions.UnGlueAction;
@@ -99,4 +100,5 @@
     public final DownloadAction download = new DownloadAction();
     public final DownloadReferrersAction downloadReferrers = new DownloadReferrersAction();
+    public final StopChangesetAction stopChangesetAction = new StopChangesetAction();
     public final JosmAction update = new UpdateDataAction();
     public final JosmAction updateSelection = new UpdateSelectionAction();
@@ -206,4 +208,5 @@
         add(fileMenu, update);
         add(fileMenu, updateSelection);
+        add(fileMenu, stopChangesetAction);
         fileMenu.addSeparator();
         add(fileMenu, exit);
Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2058)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2061)
@@ -325,4 +325,38 @@
 
     /**
+     * Update a changeset on the server.
+     *
+     * @param changeset the changeset to update
+     * @param progressMonitor the progress monitor
+     * 
+     * @throws OsmTransferException if something goes wrong.
+     */
+    public void updateChangeset(Changeset changeset, ProgressMonitor progressMonitor) throws OsmTransferException {
+        try {
+            progressMonitor.beginTask(tr("Updating changeset..."));
+            initialize(progressMonitor);
+            if (this.changeset != null && this.changeset.getId() > 0) {
+                if (this.changeset.hasEqualSemanticAttributes(changeset)) {
+                    progressMonitor.setCustomText(tr("Changeset {0} is unchanged. Skipping update.", changeset.getId()));
+                    return;
+                }
+                changeset.id = this.changeset.getId();
+                this.changeset.cloneFrom(changeset);
+                progressMonitor.setCustomText(tr("Updating changeset {0}...", changeset.getId()));
+                sendRequest(
+                        "PUT",
+                        OsmPrimitiveType.from(changeset).getAPIName() + "/" + changeset.getId(),
+                        toXml(changeset, true),
+                        progressMonitor
+                );
+                this.changeset = changeset;
+            } else
+                throw new OsmTransferException(tr("Failed to update changeset. Either there is no current changeset or the id of the current changeset is 0"));
+        } finally {
+            progressMonitor.finishTask();
+        }
+    }
+
+    /**
      * Closes a changeset on the server.
      *
Index: trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 2058)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 2061)
@@ -91,5 +91,9 @@
         try {
             progressMonitor.setTicksCount(primitives.size());
-            api.createChangeset(changeset, changesetProcessingType,progressMonitor.createSubTaskMonitor(0, false));
+            if (changesetProcessingType.isUseNew()) {
+                api.createChangeset(changeset, changesetProcessingType,progressMonitor.createSubTaskMonitor(0, false));
+            } else {
+                api.updateChangeset(changeset,progressMonitor.createSubTaskMonitor(0, false));
+            }
             uploadStartTime = System.currentTimeMillis();
             for (OsmPrimitive osm : primitives) {
@@ -98,7 +102,7 @@
                 String msg = "";
                 switch(OsmPrimitiveType.from(osm)) {
-                    case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
-                    case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
-                    case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
+                case NODE: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading node ''{4}'' (id: {5})"); break;
+                case WAY: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading way ''{4}'' (id: {5})"); break;
+                case RELATION: msg = marktr("{0}% ({1}/{2}), {3} left. Uploading relation ''{4}'' (id: {5})"); break;
                 }
                 progressMonitor.subTask(
@@ -146,5 +150,9 @@
         //
         try {
-            api.createChangeset(changeset, changesetProcessingType, progressMonitor.createSubTaskMonitor(0, false));
+            if (changesetProcessingType.isUseNew()) {
+                api.createChangeset(changeset, changesetProcessingType,progressMonitor.createSubTaskMonitor(0, false));
+            } else {
+                api.updateChangeset(changeset,progressMonitor.createSubTaskMonitor(0, false));
+            }
             processed.addAll(api.uploadDiff(primitives, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)));
         } catch(OsmTransferException e) {
@@ -173,5 +181,4 @@
 
         api.initialize(progressMonitor);
-
         try {
             // check whether we can use diff upload
