Index: trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java	(revision 2862)
+++ trunk/src/org/openstreetmap/josm/actions/search/PushbackTokenizer.java	(revision 2863)
@@ -1,4 +1,7 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.actions.search;
+
+import static org.openstreetmap.josm.tools.I18n.marktr;
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.IOException;
@@ -19,5 +22,21 @@
     }
 
-    public enum Token {NOT, OR, LEFT_PARENT, RIGHT_PARENT, COLON, EQUALS, KEY, EOF}
+    public enum Token {
+        NOT(marktr("<not>")), OR(marktr("<or>")), LEFT_PARENT(marktr("<left parent>")),
+        RIGHT_PARENT(marktr("<right parent>")), COLON(marktr("<colon>")), EQUALS(marktr("<equals>")),
+        KEY(marktr("<key>")), QUESTION_MARK(marktr("<question mark>")), EOF(marktr("<end-of-file>"));
+
+        private Token(String name) {
+            this.name = name;
+        }
+
+        private final String name;
+
+        @Override
+        public String toString() {
+            return tr(name);
+        }
+    }
+
 
     private void getChar() {
@@ -69,4 +88,7 @@
             getChar();
             return Token.OR;
+        case '?':
+            getChar();
+            return Token.QUESTION_MARK;
         case '"':
         {
@@ -90,5 +112,5 @@
         {
             StringBuilder s = new StringBuilder();
-            while (!(c == -1 || Character.isWhitespace(c) || c == '"'|| c == ':' || c == '(' || c == ')' || c == '|' || c == '=')) {
+            while (!(c == -1 || Character.isWhitespace(c) || c == '"'|| c == ':' || c == '(' || c == ')' || c == '|' || c == '=' || c == '?')) {
                 s.append((char)c);
                 getChar();
Index: trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 2862)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 2863)
@@ -122,4 +122,5 @@
                     + "<li>"+tr("<b>type=*</b> - key ''type'' with any value. Try also <b>*=value</b>, <b>type=</b>, <b>*=*</b>, <b>*=</b>") + "</li>"
                     + "<li>"+tr("<b>-name:Bak</b> - not ''Bak'' in the name.")+"</li>"
+                    + "<li>"+tr("<b>oneway?</b> - oneway=yes, true, 1 or on")+"</li>"
                     + "<li>"+tr("<b>foot:</b> - key=foot set to any value.")+"</li>"
                     + "<li>"+tr("<u>Special targets:</u>")+"</li>"
@@ -321,9 +322,9 @@
         public String toString() {
             String cs = caseSensitive ?
-                    /*case sensitive*/  trc("search", "CS") :                                
+                    /*case sensitive*/  trc("search", "CS") :
                         /*case insensitive*/  trc("search", "CI");
                     /*regex search*/
-            String rx = regexSearch ? (", " + trc("search", "RX")) : ""; 
-            return "\"" + text + "\" (" + cs + rx + ", " + mode + ")";
+                    String rx = regexSearch ? (", " + trc("search", "RX")) : "";
+                    return "\"" + text + "\" (" + cs + rx + ", " + mode + ")";
         }
 
Index: trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 2862)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 2863)
@@ -7,5 +7,4 @@
 import java.io.PushbackReader;
 import java.io.StringReader;
-import java.util.List;
 import java.util.Map.Entry;
 import java.util.regex.Matcher;
@@ -17,7 +16,7 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmUtils;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
-import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.tools.DateUtils;
@@ -36,4 +35,5 @@
  ( expression )
  -fact
+ term?
  term=term
  term:term
@@ -80,4 +80,22 @@
         }
         @Override public String toString() {return "!"+match;}
+    }
+
+    private static class BooleanMatch extends Match {
+        private final String key;
+        private final boolean defaultValue;
+
+        public BooleanMatch(String key, boolean defaultValue) {
+            this.key = key;
+            this.defaultValue = defaultValue;
+        }
+        @Override
+        public boolean match(OsmPrimitive osm) {
+            Boolean ret = OsmUtils.getOsmBoolean(osm.get(key));
+            if (ret == null)
+                return defaultValue;
+            else
+                return ret;
+        }
     }
 
@@ -430,27 +448,22 @@
 
     private static class UserMatch extends Match {
-        private User user;
+        private String user;
         public UserMatch(String user) {
             if (user.equals("anonymous")) {
                 this.user = null;
             } else {
-                List<User> users = User.getByName(user);
-                if (!users.isEmpty()) {
-                    // selecting an arbitrary user
-                    this.user = users.get(0);
-                } else {
-                    this.user = User.createLocalUser(user);
-                }
-            }
-        }
-
-        @Override public boolean match(OsmPrimitive osm) {
-            if (osm.getUser() == null && user == null) return true;
-            if (osm.getUser() == null) return false;
-            return osm.getUser().equals(user);
+                this.user = user;
+            }
+        }
+
+        @Override public boolean match(OsmPrimitive osm) {
+            if (osm.getUser() == null)
+                return user == null;
+            else
+                return osm.getUser().hasName(user);
         }
 
         @Override public String toString() {
-            return "user=" + user == null ? "" : user.getName();
+            return "user=" + user == null ? "" : user;
         }
     }
@@ -641,5 +654,5 @@
             Match expression = parseExpression();
             if (!tokenizer.readIfEqual(Token.RIGHT_PARENT))
-                throw new ParseError(tr("Missing right parenthesis"));
+                throw new ParseError(tr("Unexpected token. Expected {0}, found {1}", Token.RIGHT_PARENT, tokenizer.nextToken()));
             return expression;
         } else if (tokenizer.readIfEqual(Token.NOT))
@@ -651,4 +664,6 @@
             else if (tokenizer.readIfEqual(Token.COLON))
                 return parseKV(key, tokenizer.readText());
+            else if (tokenizer.readIfEqual(Token.QUESTION_MARK))
+                return new BooleanMatch(key, false);
             else if ("modified".equals(key))
                 return new Modified();
Index: trunk/src/org/openstreetmap/josm/data/osm/User.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/User.java	(revision 2862)
+++ trunk/src/org/openstreetmap/josm/data/osm/User.java	(revision 2863)
@@ -118,5 +118,5 @@
     }
 
-    /*
+    /**
      * Returns the list of user names
      *
@@ -127,5 +127,5 @@
     }
 
-    /*
+    /**
      * Adds a user name to the list if it is not there, yet.
      *
@@ -136,5 +136,5 @@
     }
 
-    /*
+    /**
      * Returns true if the name is in the names list
      *
