Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 3214)
@@ -26,4 +26,5 @@
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -81,4 +82,6 @@
 import org.openstreetmap.josm.gui.tagging.TaggingPreset;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
+import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionListItem;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
@@ -148,6 +151,9 @@
     private final Map<String, Map<String, Integer>> valueCount = new TreeMap<String, Map<String, Integer>>();
 
-    Comparator<String> defaultKeyComparator = String.CASE_INSENSITIVE_ORDER;
-    Comparator<String> defaultValueComparator = String.CASE_INSENSITIVE_ORDER;
+    Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
+        public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
+            return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
+        }
+    };
 
     private DataSetListenerAdapter dataChangedAdapter = new DataSetListenerAdapter(this);
@@ -191,7 +197,9 @@
 
         AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
-
+        List<AutoCompletionListItem> keyList = autocomplete.getKeys();
+        Collections.sort(keyList, defaultACItemComparator);
+        
         final AutoCompletingComboBox keys = new AutoCompletingComboBox();
-        keys.setPossibleItems(autocomplete.getKeys(defaultKeyComparator));
+        keys.setPossibleACItems(keyList);
         keys.setEditable(true);
         keys.setSelectedItem(key);
@@ -209,5 +217,5 @@
                 if (c instanceof JLabel) {
                     String str = null;
-                    str=(String) value;
+                    str=((AutoCompletionListItem) value).getValue();
                     if (valueCount.containsKey(objKey)){
                         Map<String, Integer> m=valueCount.get(objKey);
@@ -223,5 +231,9 @@
         });
         values.setEditable(true);
-        values.setPossibleItems(autocomplete.getValues(key, defaultValueComparator));
+        
+        List<AutoCompletionListItem> valueList = autocomplete.getValues(key);
+        Collections.sort(valueList, defaultACItemComparator);
+        
+        values.setPossibleACItems(valueList);
         Map<String, Integer> m=(Map<String, Integer>)propertyData.getValueAt(row, 1);
         final String selection= m.size()!=1?tr("<different>"):m.entrySet().iterator().next().getKey();
@@ -344,10 +356,20 @@
         final AutoCompletingComboBox keys = new AutoCompletingComboBox();
         AutoCompletionManager autocomplete = Main.main.getEditLayer().data.getAutoCompletionManager();
-        List<String> usedKeys =
-                new ArrayList<String>(autocomplete.getKeys(defaultKeyComparator));
-        for (int i = 0; i < propertyData.getRowCount(); ++i) {
-            usedKeys.remove(propertyData.getValueAt(i, 0));
-        }
-        keys.setPossibleItems(usedKeys);
+        List<AutoCompletionListItem> keyList = autocomplete.getKeys();
+
+        // remove the object's tag keys from the list
+        Iterator<AutoCompletionListItem> iter = keyList.iterator();
+        while (iter.hasNext()) {
+            AutoCompletionListItem item = iter.next();
+            for (int i = 0; i < propertyData.getRowCount(); ++i) {
+                if (item.getValue().equals(propertyData.getValueAt(i, 0))) {
+                    iter.remove();
+                    break;
+                }
+            }
+        }
+
+        Collections.sort(keyList, defaultACItemComparator);
+        keys.setPossibleACItems(keyList);
         keys.setEditable(true);
 
@@ -397,5 +419,9 @@
             @Override public void focusGained(FocusEvent e) {
                 String key = keys.getEditor().getItem().toString();
-                values.setPossibleItems(autocomplete.getValues(key, defaultValueComparator));
+                
+                List<AutoCompletionListItem> valueList = autocomplete.getValues(key);
+                Collections.sort(valueList, defaultACItemComparator);
+
+                values.setPossibleACItems(valueList);
                 objKey=key;
             }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java	(revision 3214)
@@ -306,4 +306,5 @@
                     public void focusGained(FocusEvent e) {
                         AutoCompletionList list = tfRole.getAutoCompletionList();
+                        list.clear();
                         getLayer().data.getAutoCompletionManager().populateWithMemberRoles(list);
                     }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberRoleCellEditor.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberRoleCellEditor.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/relation/MemberRoleCellEditor.java	(revision 3214)
@@ -43,4 +43,5 @@
         String role = (String)value;
         editor.setText(role);
+        autoCompletionList.clear();
         ds.getAutoCompletionManager().populateWithMemberRoles(autoCompletionList);
         return editor;
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/TagTable.java	(revision 3214)
@@ -409,4 +409,5 @@
         if (autocomplete == null) {
             logger.warning("argument autocomplete should not be null. Aborting.");
+            Thread.dumpStack();
             return;
         }
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletingComboBox.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletingComboBox.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletingComboBox.java	(revision 3214)
@@ -2,11 +2,16 @@
 package org.openstreetmap.josm.gui.tagging.ac;
 
+import java.awt.Component;
 import java.awt.event.FocusEvent;
 import java.awt.event.FocusListener;
 import java.util.Collection;
 
+import javax.swing.ComboBoxEditor;
 import javax.swing.ComboBoxModel;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
 import javax.swing.text.AttributeSet;
 import javax.swing.text.BadLocationException;
@@ -41,5 +46,5 @@
 
         @Override public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
-            if(selecting || (offs == 0 && str.equals(getText(0, getLength()))))
+            if (selecting || (offs == 0 && str.equals(getText(0, getLength()))))
                 return;
             boolean initial = (offs == 0 && getLength() == 0 && str.length() > 1);
@@ -58,13 +63,29 @@
             int end = start;
             String curText = getText(0, size);
+            
+            // if the text starts with a number we don't autocomplete
+            //
+            try {
+                Long.parseLong(str);
+                if (curText.length() == 0) {
+                    // we don't autocomplete on numbers
+                    return;
+                }
+                Long.parseLong(curText);
+                return;
+            } catch (NumberFormatException e) {
+                // either the new text or the current text isn't a number. We continue with
+                // autocompletion
+            }
+            
             // lookup and select a matching item
             Object item = lookupItem(curText);
             setSelectedItem(item);
-            if(initial) {
+            if (initial) {
                 start = 0;
             }
             if (item != null) {
-                String newText = item.toString();
-                if(!newText.equals(curText))
+                String newText = ((AutoCompletionListItem) item).getValue();
+                if (!newText.equals(curText))
                 {
                     selecting = true;
@@ -89,14 +110,19 @@
         private Object lookupItem(String pattern) {
             ComboBoxModel model = comboBox.getModel();
+            AutoCompletionListItem bestItem = null;
             for (int i = 0, n = model.getSize(); i < n; i++) {
-                Object currentItem = model.getElementAt(i);
-                if (currentItem.toString().startsWith(pattern))
-                    return currentItem;
-            }
-            return null;
+                AutoCompletionListItem currentItem = (AutoCompletionListItem) model.getElementAt(i);;
+                if (currentItem.getValue().startsWith(pattern)) {
+                    if (bestItem == null || currentItem.getPriority().compareTo(bestItem.getPriority()) > 0) {
+                        bestItem = currentItem;
+                    }
+                }
+            }
+            return bestItem; // may be null
         }
     }
 
     public AutoCompletingComboBox() {
+        setRenderer(new AutoCompleteListCellRenderer());
         final JTextComponent editor = (JTextComponent) this.getEditor().getEditorComponent();
         editor.setDocument(new AutoCompletingComboBoxDocument(this));
@@ -112,4 +138,49 @@
     }
 
+    /**
+     * Convert the selected item into a String
+     * that can be edited in the editor component.
+     *
+     * @param editor    the editor
+     * @param item      excepts AutoCompletionListItem, String and null
+     */
+    @Override public void configureEditor(ComboBoxEditor editor, Object item) {
+        if (item == null) {
+            editor.setItem(null);
+        } else if (item instanceof String) {
+            editor.setItem(item);
+        } else if (item instanceof AutoCompletionListItem) {
+            editor.setItem(((AutoCompletionListItem)item).getValue());
+        } else
+            throw new IllegalArgumentException();
+    }
+
+    /**
+     * Selects a given item in the ComboBox model
+     * @param item      excepts AutoCompletionListItem, String and null
+     */
+    @Override public void setSelectedItem(Object item) {
+        if (item == null) {
+            super.setSelectedItem(null);
+        } else if (item instanceof AutoCompletionListItem) {
+            super.setSelectedItem(item);
+        } else if (item instanceof String) {
+            String s = (String) item;
+            // find the string in the model or create a new item
+            for (int i=0; i< getModel().getSize(); i++) {
+                AutoCompletionListItem acItem = (AutoCompletionListItem) getModel().getElementAt(i);
+                if (s.equals(acItem.getValue())) {
+                    super.setSelectedItem(acItem);
+                    return;
+                }
+            }
+            super.setSelectedItem(new AutoCompletionListItem(s, AutoCompletionItemPritority.UNKNOWN));
+        } else
+            throw new IllegalArgumentException();
+    }
+
+    /**
+     * sets the items of the combobox to the given strings
+     */
     public void setPossibleItems(Collection<String> elems) {
         DefaultComboBoxModel model = (DefaultComboBoxModel)this.getModel();
@@ -117,8 +188,22 @@
         model.removeAllElements();
         for (String elem : elems) {
+            model.addElement(new AutoCompletionListItem(elem, AutoCompletionItemPritority.UNKNOWN));
+        }
+        this.getEditor().setItem(oldValue);
+    }
+
+    /**
+     * sets the items of the combobox to the given AutoCompletionListItems
+     */
+    public void setPossibleACItems(Collection<AutoCompletionListItem> elems) {
+        DefaultComboBoxModel model = (DefaultComboBoxModel)this.getModel();
+        Object oldValue = this.getEditor().getItem();
+        model.removeAllElements();
+        for (AutoCompletionListItem elem : elems) {
             model.addElement(elem);
         }
         this.getEditor().setItem(oldValue);
     }
+
 
     protected boolean isAutocompleteEnabled() {
@@ -129,3 +214,34 @@
         this.autocompleteEnabled = autocompleteEnabled;
     }
+
+    /**
+     * ListCellRenderer for AutoCompletingComboBox
+     * renders an AutoCompletionListItem by showing only the string value part
+     */
+    public class AutoCompleteListCellRenderer extends JLabel implements ListCellRenderer {
+
+        public AutoCompleteListCellRenderer() {
+            setOpaque(true);
+        }
+
+        public Component getListCellRendererComponent(
+                JList list,
+                Object value,
+                int index,
+                boolean isSelected,
+                boolean cellHasFocus)
+        {
+            if (isSelected) {
+                setBackground(list.getSelectionBackground());
+                setForeground(list.getSelectionForeground());
+            } else {
+                setBackground(list.getBackground());
+                setForeground(list.getForeground());
+            }
+
+            AutoCompletionListItem item = (AutoCompletionListItem) value;
+            setText(item.getValue());
+            return this;
+        }
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionItemPritority.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionItemPritority.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionItemPritority.java	(revision 3214)
@@ -2,8 +2,11 @@
 package org.openstreetmap.josm.gui.tagging.ac;
 
-public enum AutoCompletionItemPritority implements Comparable<AutoCompletionItemPritority> {
-
-    /** Indicates that a value is in the current selection. */
-    IS_IN_SELECTION,
+/**
+ * Describes the priority of an item in an autocompletion list.
+ * The selected flag is currently only used in plugins.
+ *
+ * Instances of this class are not modifiable.
+ */
+public class AutoCompletionItemPritority implements Comparable<AutoCompletionItemPritority> {
 
     /**
@@ -12,5 +15,11 @@
      * usually not used by the user.
      */
-    IS_IN_STANDARD_AND_IN_DATASET,
+    public static AutoCompletionItemPritority IS_IN_STANDARD_AND_IN_DATASET = new AutoCompletionItemPritority(true, true, false);
+
+    /**
+     * Indicates that this is an arbitrary value from the data set, i.e.
+     * the value of a tag name=*.
+     */
+    public static AutoCompletionItemPritority IS_IN_DATASET = new AutoCompletionItemPritority(true, false, false);
 
     /**
@@ -18,13 +27,66 @@
      * or a standard value for a given tag name (from the presets).
      */
-    IS_IN_STANDARD,
+    public static AutoCompletionItemPritority IS_IN_STANDARD = new AutoCompletionItemPritority(false, true, false);
+    
+    /**
+     * Indicates that this is a value from a selected object.
+     */
+    public static AutoCompletionItemPritority  IS_IN_SELECTION  = new AutoCompletionItemPritority(false, false, true);
+
+    /** Unknown priority. This is the lowest priority. */
+    public static AutoCompletionItemPritority UNKNOWN = new AutoCompletionItemPritority(false, false, false);
+
+    private final boolean inDataSet;
+    private final boolean inStandard;
+    private final boolean selected;
+
+    public AutoCompletionItemPritority(boolean inDataSet, boolean inStandard, boolean selected) {
+        this.inDataSet = inDataSet;
+        this.inStandard = inStandard;
+        this.selected = selected;
+    }
+
+    public boolean isInDataSet() {
+        return inDataSet;
+    }
+
+    public boolean isInStandard() {
+        return inStandard;
+    }
+
+    public boolean isSelected() {
+        return selected;
+    }
 
     /**
-     * Indicates that this is an arbitrary value from the data set, i.e.
-     * the value of a tag name=*.
+     * Imposes an ordering on the priorities.
+     * Currently, being in the current DataSet is worth more than being in the Presets.
      */
-    IS_IN_DATASET,
+    public int compareTo(AutoCompletionItemPritority other) {
+        int sel = new Boolean(selected).compareTo(other.selected);
+        if (sel != 0) return sel;
 
-    /** Unknown priority. This is the lowest priority. */
-    UNKNOWN
+        int ds = new Boolean(inDataSet).compareTo(other.inDataSet);
+        if (ds != 0) return ds;
+
+        int std = new Boolean(inStandard).compareTo(other.inStandard);
+        if (std != 0) return std;
+
+        return 0;
+    }
+
+    /**
+     * Merges two priorities.
+     * The resulting priority is always >= the original ones.
+     */
+    public AutoCompletionItemPritority mergeWith(AutoCompletionItemPritority other) {
+        return new AutoCompletionItemPritority(
+                        inDataSet || other.inDataSet,
+                        inStandard || other.inStandard,
+                        selected || other.selected);
+    }
+
+    @Override public String toString() {
+        return String.format("<Priority; inDataSet: %b, inStandard: %b, selected: %b>", inDataSet, inStandard, selected);
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionList.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionList.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionList.java	(revision 3214)
@@ -149,26 +149,12 @@
     }
 
-    protected void appendOrUpdatePriority(AutoCompletionListItem toadd) {
-        AutoCompletionListItem item = valutToItemMap.get(toadd.getValue());
+    protected void appendOrUpdatePriority(AutoCompletionListItem toAdd) {
+        AutoCompletionListItem item = valutToItemMap.get(toAdd.getValue());
         if (item == null) {
             // new item does not exist yet. Add it to the list
-            //
-            list.add(toadd);
-            valutToItemMap.put(toadd.getValue(), toadd);
+            list.add(toAdd);
+            valutToItemMap.put(toAdd.getValue(), toAdd);
         } else {
-            // new item already exists. Update priority if necessary
-
-            // If it is both in the dataset and in the presets, update the priority.
-            final AutoCompletionItemPritority IS_IN_DATASET = AutoCompletionItemPritority.IS_IN_DATASET;
-            final AutoCompletionItemPritority IS_IN_STANDARD = AutoCompletionItemPritority.IS_IN_STANDARD;
-            if ((toadd.getPriority() == IS_IN_STANDARD && item.getPriority() == IS_IN_DATASET) ||
-                (toadd.getPriority() == IS_IN_DATASET && item.getPriority() == IS_IN_STANDARD)) {
-
-                item.setPriority(AutoCompletionItemPritority.IS_IN_STANDARD_AND_IN_DATASET);
-            } else {
-                if (toadd.getPriority().compareTo(item.getPriority()) < 0) {
-                    item.setPriority(toadd.getPriority());
-                }
-            }
+            item.setPriority(item.getPriority().mergeWith(toAdd.getPriority()));
         }
     }
@@ -272,4 +258,8 @@
     }
 
+    List<AutoCompletionListItem> getList() {
+        return Collections.unmodifiableList(list);
+    }
+
     /**
      * removes all elements from the auto completion list
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionListItem.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionListItem.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionListItem.java	(revision 3214)
@@ -112,4 +112,5 @@
     public int compareTo(AutoCompletionListItem other) {
         int ret = this.priority.compareTo(other.priority);
+        ret = -ret; // higher priority items come first in the list
         if (ret != 0)
             return ret;
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java	(revision 3213)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java	(revision 3214)
@@ -109,11 +109,4 @@
 
     protected void cachePrimitives(Collection<? extends OsmPrimitive> primitives) {
-        if (tagCache == null) {
-            // We are coming from a DataSetListener event and
-            // rebuild has not been called yet, so do it now and 
-            // ignore the method parameter.
-            rebuild();
-            return;
-        }
         for (OsmPrimitive primitive : primitives) {
             cachePrimitiveTags(primitive);
@@ -204,11 +197,4 @@
     }
 
-    public TreeSet<String> getKeys(Comparator<String> c) {
-        TreeSet<String> ret = new TreeSet<String>(c);
-        ret.addAll(getDataKeys());
-        ret.addAll(getPresetKeys());
-        return ret;
-    }
-
     /**
      * replies the auto completion values allowed for a specific key. Replies
@@ -226,11 +212,4 @@
     }
 
-    public TreeSet<String> getValues(String key, Comparator<String> c) {
-        TreeSet<String> ret = new TreeSet<String>(c);
-        ret.addAll(getDataValues(key));
-        ret.addAll(getPresetValues(key));
-        return ret;
-    }
-
     /**
      * Replies the list of member roles
@@ -249,6 +228,18 @@
      */
     public void populateWithMemberRoles(AutoCompletionList list) {
-        list.clear();
         list.add(getRoleCache(), AutoCompletionItemPritority.IS_IN_DATASET);
+    }
+
+    /**
+     * Populates the an {@see AutoCompletionList} with the currently cached
+     * tag keys
+     *
+     * @param list the list to populate
+     * @param append true to add the keys to the list; false, to replace the keys
+     * in the list by the keys in the cache
+     */
+    public void populateWithKeys(AutoCompletionList list) {
+        list.add(getPresetKeys(), AutoCompletionItemPritority.IS_IN_STANDARD);
+        list.add(getDataKeys(), AutoCompletionItemPritority.IS_IN_DATASET);
     }
 
@@ -263,19 +254,18 @@
      */
     public void populateWithTagValues(AutoCompletionList list, String key) {
+        list.add(getPresetValues(key), AutoCompletionItemPritority.IS_IN_STANDARD);
         list.add(getDataValues(key), AutoCompletionItemPritority.IS_IN_DATASET);
-        list.add(getPresetValues(key), AutoCompletionItemPritority.IS_IN_STANDARD);
-    }
-
-    /**
-     * Populates the an {@see AutoCompletionList} with the currently cached
-     * tag keys
-     *
-     * @param list the list to populate
-     * @param append true to add the keys to the list; false, to replace the keys
-     * in the list by the keys in the cache
-     */
-    public void populateWithKeys(AutoCompletionList list) {
-        list.add(getDataKeys(), AutoCompletionItemPritority.IS_IN_DATASET);
-        list.add(getPresetKeys(), AutoCompletionItemPritority.IS_IN_STANDARD);
+    }
+
+    public List<AutoCompletionListItem> getKeys() {
+        AutoCompletionList list = new AutoCompletionList();
+        populateWithKeys(list);
+        return new ArrayList<AutoCompletionListItem>(list.getList());
+    }
+
+    public List<AutoCompletionListItem> getValues(String key) {
+        AutoCompletionList list = new AutoCompletionList();
+        populateWithTagValues(list, key);
+        return new ArrayList<AutoCompletionListItem>(list.getList());
     }
 
@@ -286,4 +276,6 @@
 
     public void primtivesAdded(PrimitivesAddedEvent event) {
+        if (dirty)
+            return;
         cachePrimitives(event.getPrimitives());
     }
@@ -294,4 +286,6 @@
 
     public void tagsChanged(TagsChangedEvent event) {
+        if (dirty)
+            return;
         Map<String, String> newKeys = event.getPrimitive().getKeys();
         Map<String, String> oldKeys = event.getOriginalKeys();
