Index: src/org/openstreetmap/josm/Main.java
===================================================================
--- src/org/openstreetmap/josm/Main.java	(revision 190)
+++ src/org/openstreetmap/josm/Main.java	(revision 191)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.actions.DownloadAction.DownloadTask;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
+import org.openstreetmap.josm.actions.search.SearchAction;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.Preferences;
@@ -39,5 +40,4 @@
 import org.openstreetmap.josm.gui.PleaseWaitDialog;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
-import org.openstreetmap.josm.gui.dialogs.SelectionListDialog;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
@@ -322,5 +322,5 @@
 		if (args.containsKey("selection"))
 			for (String s : args.get("selection"))
-				SelectionListDialog.search(s, SelectionListDialog.SearchMode.add);
+				SearchAction.search(s, SearchAction.SearchMode.add);
 	}
 
Index: src/org/openstreetmap/josm/actions/search/QuickSearchAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/QuickSearchAction.java	(revision 191)
+++ src/org/openstreetmap/josm/actions/search/QuickSearchAction.java	(revision 191)
@@ -0,0 +1,134 @@
+package org.openstreetmap.josm.actions.search;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.Vector;
+
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.data.osm.visitor.NameVisitor;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import uk.co.wilson.xml.MinML2;
+
+public class QuickSearchAction extends JosmAction {
+
+	public final JTextField searchField = new JTextField(10);
+
+	public QuickSearchAction() {
+		super(tr("Quick Search"), "dialogs/search", tr("Try to search for the input string, first locally, then on geonames.org"), KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK, false);
+	}
+
+	private static class GeoNamesHit {
+		String name;
+		LatLon lat;
+		String lng;
+		String countryCode;
+		String countryName;
+	}
+
+	private class GeoNamesReader extends MinML2 {
+		Collection<GeoNamesHit> result;
+		GeoNamesHit current;
+		String nextFieldName;
+		String characters;
+
+		@Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+			nextFieldName = qName;
+			if (qName.equals("geoname"))
+				current = new GeoNamesHit();
+			characters = "";
+		}
+
+		@Override public void characters(char[] ch, int start, int length) {
+			String s = new String(ch, start, length);
+			characters += s;
+		}
+
+		@Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+			if (qName.equals("geoname")) {
+				result.add(current);
+				return;
+			}
+			if ("|name|lat|lng|countryCode|countryName|".indexOf("|"+qName+"|") == -1)
+				return;
+			try {
+				current.getClass().getField(qName).set(current, characters);
+			} catch (Exception e) {
+				throw new SAXException(e);
+			}
+		}
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		String search = searchField.getText();
+		SearchCompiler.Match matcher = SearchCompiler.compile(search);
+		Vector<Vector<Object>> result = new Vector<Vector<Object>>();
+		Vector<String> columns = new Vector<String>();
+
+		for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
+			if (matcher.match(osm)) {
+				Vector<Object> row = new Vector<Object>();
+				NameVisitor v = new NameVisitor();
+				BoundingXYVisitor bv = new BoundingXYVisitor();
+				osm.visit(v);
+				osm.visit(bv);
+				LatLon center = bv.getBounds().center();
+				row.add(v.icon);
+				row.add(v.name);
+				row.add(center.lat()+" / "+center.lon());
+				result.add(row);
+			}
+		}
+		if (!result.isEmpty()) {
+			columns.add("");
+			columns.add(tr("Name"));
+			columns.add(tr("Location"));
+		} else {
+			columns.add(tr("Name"));
+			columns.add(tr("Country"));
+			columns.add(tr("Location"));
+			String geoNamesUrl = Main.pref.get("search.geonames.url", "http://ws.geonames.org/search");
+			GeoNamesReader r = new GeoNamesReader();
+			try {
+				URLConnection con = new URL(geoNamesUrl).openConnection();
+				r.parse(new InputStreamReader(con.getInputStream()));
+			} catch (SAXException e1) {
+				e1.printStackTrace();
+				// just nothing is found if xml response has parsing problems
+			} catch (IOException e1) {
+				e1.printStackTrace();
+				// just nothing is found if connection problems to geonames
+			}
+			for (GeoNamesHit g : r.result) {
+				Vector<String> row = new Vector<String>();
+				row.add(g.name);
+				row.add(g.countryName+" ("+g.countryCode+")");
+				row.add(g.lat+" / "+g.lng);
+			}
+		}
+		if (result.isEmpty()) {
+			JOptionPane.showMessageDialog(Main.parent, tr("No hits found."));
+			return;
+		}
+
+		JTable hits = new JTable(result, columns);
+		JOptionPane.showMessageDialog(Main.parent, new JScrollPane(hits));
+	}
+}
Index: src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 191)
+++ src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 191)
@@ -0,0 +1,97 @@
+package org.openstreetmap.josm.actions.search;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.util.Collection;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.tools.GBC;
+
+public class SearchAction extends JosmAction {
+	public static enum SearchMode {replace, add, remove}
+
+    private String lastSearch = "";
+
+    public SearchAction() {
+    	super(tr("Search"), "dialogs/search", tr("Search for objects."), KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK, true);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    	if (Main.map == null) {
+    		JOptionPane.showMessageDialog(Main.parent, tr("No data loaded."));
+    		return;
+    	}
+    	JLabel label = new JLabel(tr("Please enter a search string."));
+    	final JTextField input = new JTextField(lastSearch);
+    	input.setToolTipText(tr("<html>Fulltext search.<ul>" +
+    			"<li><code>Baker Street</code>  - 'Baker' and 'Street' in any key or name.</li>" +
+    			"<li><code>\"Baker Street\"</code>  - 'Baker Street' in any key or name.</li>" +
+    			"<li><code>name:Bak</code>  - 'Bak' anywhere in the name.</li>" +
+    			"<li><code>-name:Bak</code>  - not 'Bak' in the name.</li>" +
+    			"<li><code>foot:</code>  - key=foot set to any value." +
+    	"</ul></html>"));
+    
+    	JRadioButton replace = new JRadioButton(tr("replace selection"), true);
+    	JRadioButton add = new JRadioButton(tr("add to selection"), false);
+    	JRadioButton remove = new JRadioButton(tr("remove from selection"), false);
+    	ButtonGroup bg = new ButtonGroup();
+    	bg.add(replace);
+    	bg.add(add);
+    	bg.add(remove);
+    
+    	JPanel p = new JPanel(new GridBagLayout());
+    	p.add(label, GBC.eop());
+    	p.add(input, GBC.eop().fill(GBC.HORIZONTAL));
+    	p.add(replace, GBC.eol());
+    	p.add(add, GBC.eol());
+    	p.add(remove, GBC.eol());
+    	JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null){
+    		@Override public void selectInitialValue() {
+    			input.requestFocusInWindow();
+    			input.selectAll();
+    		}
+    	};
+    	pane.createDialog(Main.parent,tr("Search")).setVisible(true);
+    	if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
+    		return;
+    	lastSearch = input.getText();
+    	SearchAction.SearchMode mode = replace.isSelected() ? SearchAction.SearchMode.replace : (add.isSelected() ? SearchAction.SearchMode.add : SearchAction.SearchMode.remove);
+    	search(lastSearch, mode);
+    }
+
+	public static void search(String search, SearchMode mode) {
+    	if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://") || search.startsWith("file:/")) {
+    		SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode);
+    		if (loader.url != null) {
+    			Main.worker.execute(loader);
+    			return;
+    		}
+    	}
+    	Collection<OsmPrimitive> sel = Main.ds.getSelected();
+    	SearchCompiler.Match matcher = SearchCompiler.compile(search);
+    	for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
+    		if (mode == SearchMode.replace) {
+    			if (matcher.match(osm))
+    				sel.add(osm);
+    			else
+    				sel.remove(osm);
+    		} else if (mode == SearchMode.add && !osm.selected && matcher.match(osm))
+    			sel.add(osm);
+    		else if (mode == SearchMode.remove && osm.selected && matcher.match(osm))
+    			sel.remove(osm);
+    	}
+    	Main.ds.setSelected(sel);
+    }
+}
Index: src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 191)
+++ src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 191)
@@ -0,0 +1,282 @@
+package org.openstreetmap.josm.actions.search;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.StringReader;
+import java.util.Map.Entry;
+
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Segment;
+import org.openstreetmap.josm.data.osm.Way;
+
+/**
+ * Implements a google-like search.
+ * @author Imi
+ */
+public class SearchCompiler {
+
+	abstract public static class Match {
+		abstract public boolean match(OsmPrimitive osm);
+	}
+
+	private static class Always extends Match {
+		@Override public boolean match(OsmPrimitive osm) {
+			return true;
+		}
+	}
+
+	private static class Not extends Match {
+		private final Match match;
+		public Not(Match match) {this.match = match;}
+		@Override public boolean match(OsmPrimitive osm) {
+			return !match.match(osm);
+		}
+		@Override public String toString() {return "!"+match;}
+	}
+
+	private static class And extends Match {
+		private Match lhs;
+		private Match rhs;
+		public And(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
+		@Override public boolean match(OsmPrimitive osm) {
+			return lhs.match(osm) && rhs.match(osm);
+		}
+		@Override public String toString() {return lhs+" && "+rhs;}
+	}
+
+	private static class Or extends Match {
+		private Match lhs;
+		private Match rhs;
+		public Or(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
+		@Override public boolean match(OsmPrimitive osm) {
+			return lhs.match(osm) || rhs.match(osm);
+		}
+		@Override public String toString() {return lhs+" || "+rhs;}
+	}
+
+	private static class Id extends Match {
+		private long id;
+		public Id(long id) {this.id = id;}
+		@Override public boolean match(OsmPrimitive osm) {
+			return osm.id == id;
+		}
+		@Override public String toString() {return "id="+id;}
+	}
+
+	private static class KeyValue extends Match {
+		private String key;
+		private String value;
+		boolean notValue;
+		public KeyValue(String key, String value, boolean notValue) {this.key = key; this.value = value; this.notValue = notValue;}
+		@Override public boolean match(OsmPrimitive osm) {
+			String value = null;
+			if (key.equals("timestamp"))
+				value = osm.getTimeStr();
+			else
+				value = osm.get(key);
+			if (value == null)
+				return notValue;
+			return (value.toLowerCase().indexOf(this.value.toLowerCase()) != -1) != notValue;
+		}
+		@Override public String toString() {return key+"="+(notValue?"!":"")+value;}
+	}
+
+	private static class Any extends Match {
+		private String s;
+		public Any(String s) {this.s = s;}
+		@Override public boolean match(OsmPrimitive osm) {
+			if (osm.keys == null)
+				return s.equals("");
+			for (Entry<String, String> e : osm.keys.entrySet())
+				if (e.getKey().toLowerCase().indexOf(s.toLowerCase()) != -1 
+						|| e.getValue().toLowerCase().indexOf(s.toLowerCase()) != -1)
+					return true;
+			return false;
+		}
+		@Override public String toString() {return s;}
+	}
+
+	private static class ExactType extends Match {
+		private String type;
+		public ExactType(String type) {this.type = type;}
+		@Override public boolean match(OsmPrimitive osm) {
+			if (osm instanceof Node)
+				return type.equals("node");
+			if (osm instanceof Segment)
+				return type.equals("segment");
+			if (osm instanceof Way)
+				return type.equals("way");
+			throw new IllegalStateException("unknown class "+osm.getClass());
+		}
+		@Override public String toString() {return "type="+type;}
+	}
+
+	private static class Modified extends Match {
+		@Override public boolean match(OsmPrimitive osm) {
+			return osm.modified;
+		}
+		@Override public String toString() {return "modified";}
+	}
+	
+	private static class Selected extends Match {
+		@Override public boolean match(OsmPrimitive osm) {
+			return osm.selected;
+		}
+		@Override public String toString() {return "selected";}
+	}
+
+	private static class Incomplete extends Match {
+		@Override public boolean match(OsmPrimitive osm) {
+			return osm instanceof Way && ((Way)osm).isIncomplete();
+		}
+		@Override public String toString() {return "incomplete";}
+	}
+	
+	public static Match compile(String searchStr) {
+		return new SearchCompiler().parse(new PushbackReader(new StringReader(searchStr)));
+	}
+
+
+	/**
+	 * The token returned is <code>null</code> or starts with an identifier character:
+	 * - for an '-'. This will be the only character
+	 * : for an key. The value is the next token
+	 * | for "OR"
+	 * ' ' for anything else.
+	 * @return The next token in the stream.
+	 */
+	private String nextToken(PushbackReader search) {
+		try {
+			int next;
+			char c = ' ';
+			while (c == ' ' || c == '\t' || c == '\n') {
+				next = search.read();
+				if (next == -1)
+					return null;
+				c = (char)next;
+			}
+			StringBuilder s;
+			switch (c) {
+			case '-':
+				return "-";
+			case '"':
+				s = new StringBuilder(" ");
+				for (int nc = search.read(); nc != -1 && nc != '"'; nc = search.read())
+					s.append((char)nc);
+				int nc = search.read();
+				if (nc != -1 && (char)nc == ':')
+					return ":"+s.toString();
+				if (nc != -1)
+					search.unread(nc);
+				return s.toString();
+			default:
+				s = new StringBuilder();
+			for (;;) {
+				s.append(c);
+				next = search.read();
+				if (next == -1) {
+					if (s.toString().equals("OR"))
+						return "|";
+					return " "+s.toString();
+				}
+				c = (char)next;
+				if (c == ' ' || c == '\t' || c == ':' || c == '"') {
+					if (c == ':')
+						return ":"+s.toString();
+					search.unread(next);
+					if (s.toString().equals("OR"))
+						return "|";
+					return " "+s.toString();
+				}
+			}
+			}
+		} catch (IOException e) {
+			throw new RuntimeException(e.getMessage(), e);
+		}		
+	}
+
+
+	private boolean notKey = false;
+	private boolean notValue = false;
+	private boolean or = false;
+	private String key = null;
+	String token = null;
+	private Match build() {
+		String value = token.substring(1);
+		if (key == null) {
+			Match c = null;
+			if (value.equals("modified"))
+				c = new Modified();
+			else if (value.equals("incomplete"))
+				c = new Incomplete();
+			else if (value.equals("selected"))
+				c = new Selected();
+			else
+				c = new Any(value);
+			return notValue ? new Not(c) : c;
+		}
+		Match c;
+		if (key.equals("type"))
+			c = new ExactType(value);
+		else if (key.equals("property")) {
+			String realKey = "", realValue = value;
+			int eqPos = value.indexOf("=");
+			if (eqPos != -1) {
+				realKey = value.substring(0,eqPos);
+				realValue = value.substring(eqPos+1);
+			}
+			c = new KeyValue(realKey, realValue, notValue);
+		} else if (key.equals("id")) {
+			try {
+				c = new Id(Long.parseLong(value));
+			} catch (NumberFormatException x) {
+				c = new Id(0);
+			}
+			if (notValue)
+				c = new Not(c);
+		} else
+			c = new KeyValue(key, value, notValue);
+		if (notKey)
+			return new Not(c);
+		return c;
+	}
+
+	private Match parse(PushbackReader search) {
+		Match result = null;
+		for (token = nextToken(search); token != null; token = nextToken(search)) {
+			if (token.equals("-"))
+				notValue = true;
+			else if (token.equals("|")) {
+				if (result == null)
+					continue;
+				or = true;
+				notValue = false;
+			} else if (token.startsWith(":")) {
+				if (key == null) {
+					key = token.substring(1);
+					notKey = notValue;
+					notValue = false;
+				} else
+					key += token.substring(1);
+			} else {
+				Match current = build();
+				if (result == null)
+					result = current;
+				else
+					result = or ? new Or(result, current) : new And(result, current);
+					key = null;
+					notKey = false;
+					notValue = false;
+					or = false;
+			}
+		}
+		// if "key:" was the last search
+		if (key != null) {
+			token = " ";
+			Match current = build();
+			result = (result == null) ? current : new And(result, current);
+		}
+		return result == null ? new Always() : result;
+	}
+}
Index: src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java
===================================================================
--- src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java	(revision 191)
+++ src/org/openstreetmap/josm/actions/search/SelectionWebsiteLoader.java	(revision 191)
@@ -0,0 +1,70 @@
+/**
+ * 
+ */
+package org.openstreetmap.josm.actions.search;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.io.OsmIdReader;
+import org.openstreetmap.josm.io.ProgressInputStream;
+import org.xml.sax.SAXException;
+
+public class SelectionWebsiteLoader extends PleaseWaitRunnable {
+	public final URL url;
+	public Collection<OsmPrimitive> sel;
+	private final SearchAction.SearchMode mode;
+	private OsmIdReader idReader = new OsmIdReader();
+	public SelectionWebsiteLoader(String urlStr, SearchAction.SearchMode mode) {
+		super(tr("Load Selection"));
+		this.mode = mode;
+		URL u = null;
+		try {u = new URL(urlStr);} catch (MalformedURLException e) {}
+		this.url = u;
+	}
+	@Override protected void realRun() {
+		Main.pleaseWaitDlg.currentAction.setText(tr("Contact {0}...", url.getHost()));
+		sel = mode != SearchAction.SearchMode.remove ? new LinkedList<OsmPrimitive>() : Main.ds.allNonDeletedPrimitives();
+		try {
+			URLConnection con = url.openConnection();
+			InputStream in = new ProgressInputStream(con, Main.pleaseWaitDlg);
+			Main.pleaseWaitDlg.currentAction.setText(tr("Downloading..."));
+			Map<Long, String> ids = idReader.parseIds(in);
+			for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
+				if (ids.containsKey(osm.id) && osm.getClass().getName().toLowerCase().endsWith(ids.get(osm.id))) {
+					if (mode == SearchAction.SearchMode.remove)
+						sel.remove(osm);
+					else
+						sel.add(osm);
+				}
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not read from url: \"{0}\"",url));
+		} catch (SAXException e) {
+			e.printStackTrace();
+			JOptionPane.showMessageDialog(Main.parent,tr("Parsing error in url: \"{0}\"",url));
+		}
+	}
+	@Override protected void cancel() {
+		sel = null;
+		idReader.cancel();
+	}
+	@Override protected void finish() {
+		if (sel != null)
+			Main.ds.setSelected(sel);
+	}
+}
Index: src/org/openstreetmap/josm/data/Bounds.java
===================================================================
--- src/org/openstreetmap/josm/data/Bounds.java	(revision 190)
+++ src/org/openstreetmap/josm/data/Bounds.java	(revision 191)
@@ -40,4 +40,14 @@
 
 	/**
+	 * @return Center of the bounding box.
+	 */
+	public LatLon center() {
+		// not sure, whether this calculation is right.. maybe there is some
+		// more complex calculation needed to get a center of a spherical
+		// dimension?
+		return new LatLon((min.lat()+max.lat())/2, (min.lon()+max.lon())/2);
+	}
+	
+	/**
 	 * Extend the bounds if necessary to include the given point.
 	 */
Index: src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainMenu.java	(revision 190)
+++ src/org/openstreetmap/josm/gui/MainMenu.java	(revision 191)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.actions.UnselectAllAction;
 import org.openstreetmap.josm.actions.UploadAction;
+import org.openstreetmap.josm.actions.search.SearchAction;
 
 /**
@@ -44,4 +45,5 @@
 	public final Action selectAll = new SelectAllAction();
 	public final Action unselectAll = new UnselectAllAction();
+	public final Action search = new SearchAction();
 	public final NewAction newAction = new NewAction();
 	public final OpenAction open = new OpenAction();
@@ -88,4 +90,6 @@
 		editMenu.add(unselectAll);
 		editMenu.addSeparator();
+		editMenu.add(search);
+		editMenu.addSeparator();
 		editMenu.add(reverseSegment);
 		editMenu.add(splitWay);
Index: src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 190)
+++ src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 191)
@@ -4,5 +4,4 @@
 
 import java.awt.BorderLayout;
-import java.awt.GridBagLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
@@ -11,24 +10,13 @@
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.Map;
 
-import javax.swing.ButtonGroup;
 import javax.swing.DefaultListModel;
 import javax.swing.JButton;
-import javax.swing.JLabel;
 import javax.swing.JList;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
-import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
-import javax.swing.JTextField;
 import javax.swing.ListSelectionModel;
 
@@ -37,11 +25,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
-import org.openstreetmap.josm.gui.PleaseWaitRunnable;
-import org.openstreetmap.josm.io.OsmIdReader;
-import org.openstreetmap.josm.io.ProgressInputStream;
-import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.josm.tools.SearchCompiler;
-import org.xml.sax.SAXException;
 
 /**
@@ -53,51 +35,4 @@
  */
 public class SelectionListDialog extends ToggleDialog implements SelectionChangedListener {
-	public static enum SearchMode {replace, add, remove}
-
-	private static class SelectionWebsiteLoader extends PleaseWaitRunnable {
-		public final URL url;
-		public Collection<OsmPrimitive> sel;
-		private final SearchMode mode;
-		private OsmIdReader idReader = new OsmIdReader();
-		public SelectionWebsiteLoader(String urlStr, SearchMode mode) {
-			super(tr("Load Selection"));
-			this.mode = mode;
-			URL u = null;
-			try {u = new URL(urlStr);} catch (MalformedURLException e) {}
-			this.url = u;
-		}
-		@Override protected void realRun() {
-			Main.pleaseWaitDlg.currentAction.setText(tr("Contact {0}...", url.getHost()));
-			sel = mode != SearchMode.remove ? new LinkedList<OsmPrimitive>() : Main.ds.allNonDeletedPrimitives();
-			try {
-				URLConnection con = url.openConnection();
-				InputStream in = new ProgressInputStream(con, Main.pleaseWaitDlg);
-				Main.pleaseWaitDlg.currentAction.setText(tr("Downloading..."));
-				Map<Long, String> ids = idReader.parseIds(in);
-				for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
-					if (ids.containsKey(osm.id) && osm.getClass().getName().toLowerCase().endsWith(ids.get(osm.id))) {
-						if (mode == SearchMode.remove)
-							sel.remove(osm);
-						else
-							sel.add(osm);
-					}
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-				JOptionPane.showMessageDialog(Main.parent, tr("Could not read from url: \"{0}\"",url));
-			} catch (SAXException e) {
-				e.printStackTrace();
-				JOptionPane.showMessageDialog(Main.parent,tr("Parsing error in url: \"{0}\"",url));
-			}
-		}
-		@Override protected void cancel() {
-			sel = null;
-			idReader.cancel();
-		}
-		@Override protected void finish() {
-			if (sel != null)
-				Main.ds.setSelected(sel);
-		}
-	}
 
 	/**
@@ -138,44 +73,5 @@
 		}));
 
-		buttonPanel.add(createButton("Search", "dialogs/search", "Search for objects.", new ActionListener(){
-			private String lastSearch = "";
-			public void actionPerformed(ActionEvent e) {
-				JLabel label = new JLabel(tr("Please enter a search string."));
-				final JTextField input = new JTextField(lastSearch);
-				input.setToolTipText(tr("<html>Fulltext search.<ul>" +
-						"<li><code>Baker Street</code>  - 'Baker' and 'Street' in any key or name.</li>" +
-						"<li><code>\"Baker Street\"</code>  - 'Baker Street' in any key or name.</li>" +
-						"<li><code>name:Bak</code>  - 'Bak' anywhere in the name.</li>" +
-						"<li><code>-name:Bak</code>  - not 'Bak' in the name.</li>" +
-						"<li><code>foot:</code>  - key=foot set to any value." +
-				"</ul></html>"));
-
-				JRadioButton replace = new JRadioButton(tr("replace selection"), true);
-				JRadioButton add = new JRadioButton(tr("add to selection"), false);
-				JRadioButton remove = new JRadioButton(tr("remove from selection"), false);
-				ButtonGroup bg = new ButtonGroup();
-				bg.add(replace);
-				bg.add(add);
-				bg.add(remove);
-
-				JPanel p = new JPanel(new GridBagLayout());
-				p.add(label, GBC.eop());
-				p.add(input, GBC.eop().fill(GBC.HORIZONTAL));
-				p.add(replace, GBC.eol());
-				p.add(add, GBC.eol());
-				p.add(remove, GBC.eol());
-				JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null){
-					@Override public void selectInitialValue() {
-						input.requestFocusInWindow();
-					}
-				};
-				pane.createDialog(Main.parent,tr("Search")).setVisible(true);
-				if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue()))
-					return;
-				lastSearch = input.getText();
-				SearchMode mode = replace.isSelected() ? SearchMode.replace : (add.isSelected() ? SearchMode.add : SearchMode.remove);
-				search(lastSearch, mode);
-			}
-		}));
+		buttonPanel.add(createButton("Search", "dialogs/search", "Search for objects.", Main.main.menu.search));
 
 		add(buttonPanel, BorderLayout.SOUTH);
@@ -229,27 +125,3 @@
 		Main.ds.setSelected(sel);
 	}
-
-	public static void search(String search, SearchMode mode) {
-		if (search.startsWith("http://") || search.startsWith("ftp://") || search.startsWith("https://") || search.startsWith("file:/")) {
-			SelectionWebsiteLoader loader = new SelectionWebsiteLoader(search, mode);
-			if (loader.url != null) {
-				Main.worker.execute(loader);
-				return;
-			}
-		}
-		Collection<OsmPrimitive> sel = Main.ds.getSelected();
-		SearchCompiler.Match matcher = SearchCompiler.compile(search);
-		for (OsmPrimitive osm : Main.ds.allNonDeletedPrimitives()) {
-			if (mode == SearchMode.replace) {
-				if (matcher.match(osm))
-					sel.add(osm);
-				else
-					sel.remove(osm);
-			} else if (mode == SearchMode.add && !osm.selected && matcher.match(osm))
-				sel.add(osm);
-			else if (mode == SearchMode.remove && osm.selected && matcher.match(osm))
-				sel.remove(osm);
-		}
-		Main.ds.setSelected(sel);
-	}
 }
Index: src/org/openstreetmap/josm/tools/SearchCompiler.java
===================================================================
--- src/org/openstreetmap/josm/tools/SearchCompiler.java	(revision 190)
+++ 	(revision )
@@ -1,282 +1,0 @@
-package org.openstreetmap.josm.tools;
-
-import java.io.IOException;
-import java.io.PushbackReader;
-import java.io.StringReader;
-import java.util.Map.Entry;
-
-import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Segment;
-import org.openstreetmap.josm.data.osm.Way;
-
-/**
- * Implements a google-like search.
- * @author Imi
- */
-public class SearchCompiler {
-
-	abstract public static class Match {
-		abstract public boolean match(OsmPrimitive osm);
-	}
-
-	private static class Always extends Match {
-		@Override public boolean match(OsmPrimitive osm) {
-			return true;
-		}
-	}
-
-	private static class Not extends Match {
-		private final Match match;
-		public Not(Match match) {this.match = match;}
-		@Override public boolean match(OsmPrimitive osm) {
-			return !match.match(osm);
-		}
-		@Override public String toString() {return "!"+match;}
-	}
-
-	private static class And extends Match {
-		private Match lhs;
-		private Match rhs;
-		public And(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
-		@Override public boolean match(OsmPrimitive osm) {
-			return lhs.match(osm) && rhs.match(osm);
-		}
-		@Override public String toString() {return lhs+" && "+rhs;}
-	}
-
-	private static class Or extends Match {
-		private Match lhs;
-		private Match rhs;
-		public Or(Match lhs, Match rhs) {this.lhs = lhs; this.rhs = rhs;}
-		@Override public boolean match(OsmPrimitive osm) {
-			return lhs.match(osm) || rhs.match(osm);
-		}
-		@Override public String toString() {return lhs+" || "+rhs;}
-	}
-
-	private static class Id extends Match {
-		private long id;
-		public Id(long id) {this.id = id;}
-		@Override public boolean match(OsmPrimitive osm) {
-			return osm.id == id;
-		}
-		@Override public String toString() {return "id="+id;}
-	}
-
-	private static class KeyValue extends Match {
-		private String key;
-		private String value;
-		boolean notValue;
-		public KeyValue(String key, String value, boolean notValue) {this.key = key; this.value = value; this.notValue = notValue;}
-		@Override public boolean match(OsmPrimitive osm) {
-			String value = null;
-			if (key.equals("timestamp"))
-				value = osm.getTimeStr();
-			else
-				value = osm.get(key);
-			if (value == null)
-				return notValue;
-			return (value.toLowerCase().indexOf(this.value.toLowerCase()) != -1) != notValue;
-		}
-		@Override public String toString() {return key+"="+(notValue?"!":"")+value;}
-	}
-
-	private static class Any extends Match {
-		private String s;
-		public Any(String s) {this.s = s;}
-		@Override public boolean match(OsmPrimitive osm) {
-			if (osm.keys == null)
-				return s.equals("");
-			for (Entry<String, String> e : osm.keys.entrySet())
-				if (e.getKey().toLowerCase().indexOf(s.toLowerCase()) != -1 
-						|| e.getValue().toLowerCase().indexOf(s.toLowerCase()) != -1)
-					return true;
-			return false;
-		}
-		@Override public String toString() {return s;}
-	}
-
-	private static class ExactType extends Match {
-		private String type;
-		public ExactType(String type) {this.type = type;}
-		@Override public boolean match(OsmPrimitive osm) {
-			if (osm instanceof Node)
-				return type.equals("node");
-			if (osm instanceof Segment)
-				return type.equals("segment");
-			if (osm instanceof Way)
-				return type.equals("way");
-			throw new IllegalStateException("unknown class "+osm.getClass());
-		}
-		@Override public String toString() {return "type="+type;}
-	}
-
-	private static class Modified extends Match {
-		@Override public boolean match(OsmPrimitive osm) {
-			return osm.modified;
-		}
-		@Override public String toString() {return "modified";}
-	}
-	
-	private static class Selected extends Match {
-		@Override public boolean match(OsmPrimitive osm) {
-			return osm.selected;
-		}
-		@Override public String toString() {return "selected";}
-	}
-
-	private static class Incomplete extends Match {
-		@Override public boolean match(OsmPrimitive osm) {
-			return osm instanceof Way && ((Way)osm).isIncomplete();
-		}
-		@Override public String toString() {return "incomplete";}
-	}
-	
-	public static Match compile(String searchStr) {
-		return new SearchCompiler().parse(new PushbackReader(new StringReader(searchStr)));
-	}
-
-
-	/**
-	 * The token returned is <code>null</code> or starts with an identifier character:
-	 * - for an '-'. This will be the only character
-	 * : for an key. The value is the next token
-	 * | for "OR"
-	 * ' ' for anything else.
-	 * @return The next token in the stream.
-	 */
-	private String nextToken(PushbackReader search) {
-		try {
-			int next;
-			char c = ' ';
-			while (c == ' ' || c == '\t' || c == '\n') {
-				next = search.read();
-				if (next == -1)
-					return null;
-				c = (char)next;
-			}
-			StringBuilder s;
-			switch (c) {
-			case '-':
-				return "-";
-			case '"':
-				s = new StringBuilder(" ");
-				for (int nc = search.read(); nc != -1 && nc != '"'; nc = search.read())
-					s.append((char)nc);
-				int nc = search.read();
-				if (nc != -1 && (char)nc == ':')
-					return ":"+s.toString();
-				if (nc != -1)
-					search.unread(nc);
-				return s.toString();
-			default:
-				s = new StringBuilder();
-			for (;;) {
-				s.append(c);
-				next = search.read();
-				if (next == -1) {
-					if (s.toString().equals("OR"))
-						return "|";
-					return " "+s.toString();
-				}
-				c = (char)next;
-				if (c == ' ' || c == '\t' || c == ':' || c == '"') {
-					if (c == ':')
-						return ":"+s.toString();
-					search.unread(next);
-					if (s.toString().equals("OR"))
-						return "|";
-					return " "+s.toString();
-				}
-			}
-			}
-		} catch (IOException e) {
-			throw new RuntimeException(e.getMessage(), e);
-		}		
-	}
-
-
-	private boolean notKey = false;
-	private boolean notValue = false;
-	private boolean or = false;
-	private String key = null;
-	String token = null;
-	private Match build() {
-		String value = token.substring(1);
-		if (key == null) {
-			Match c = null;
-			if (value.equals("modified"))
-				c = new Modified();
-			else if (value.equals("incomplete"))
-				c = new Incomplete();
-			else if (value.equals("selected"))
-				c = new Selected();
-			else
-				c = new Any(value);
-			return notValue ? new Not(c) : c;
-		}
-		Match c;
-		if (key.equals("type"))
-			c = new ExactType(value);
-		else if (key.equals("property")) {
-			String realKey = "", realValue = value;
-			int eqPos = value.indexOf("=");
-			if (eqPos != -1) {
-				realKey = value.substring(0,eqPos);
-				realValue = value.substring(eqPos+1);
-			}
-			c = new KeyValue(realKey, realValue, notValue);
-		} else if (key.equals("id")) {
-			try {
-				c = new Id(Long.parseLong(value));
-			} catch (NumberFormatException x) {
-				c = new Id(0);
-			}
-			if (notValue)
-				c = new Not(c);
-		} else
-			c = new KeyValue(key, value, notValue);
-		if (notKey)
-			return new Not(c);
-		return c;
-	}
-
-	private Match parse(PushbackReader search) {
-		Match result = null;
-		for (token = nextToken(search); token != null; token = nextToken(search)) {
-			if (token.equals("-"))
-				notValue = true;
-			else if (token.equals("|")) {
-				if (result == null)
-					continue;
-				or = true;
-				notValue = false;
-			} else if (token.startsWith(":")) {
-				if (key == null) {
-					key = token.substring(1);
-					notKey = notValue;
-					notValue = false;
-				} else
-					key += token.substring(1);
-			} else {
-				Match current = build();
-				if (result == null)
-					result = current;
-				else
-					result = or ? new Or(result, current) : new And(result, current);
-					key = null;
-					notKey = false;
-					notValue = false;
-					or = false;
-			}
-		}
-		// if "key:" was the last search
-		if (key != null) {
-			token = " ";
-			Match current = build();
-			result = (result == null) ? current : new And(result, current);
-		}
-		return result == null ? new Always() : result;
-	}
-}
