Index: /.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /.settings/org.eclipse.jdt.core.prefs	(revision 79)
+++ /.settings/org.eclipse.jdt.core.prefs	(revision 79)
@@ -0,0 +1,248 @@
+#Mon Apr 03 21:11:54 CEST 2006
+eclipse.preferences.version=1
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
+org.eclipse.jdt.core.formatter.comment.format_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true
Index: /.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- /.settings/org.eclipse.jdt.ui.prefs	(revision 79)
+++ /.settings/org.eclipse.jdt.ui.prefs	(revision 79)
@@ -0,0 +1,4 @@
+#Mon Apr 03 21:08:35 CEST 2006
+eclipse.preferences.version=1
+formatter_profile=_josm
+formatter_settings_version=10
Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 78)
+++ /src/org/openstreetmap/josm/Main.java	(revision 79)
@@ -35,7 +35,8 @@
 import org.openstreetmap.josm.actions.UndoAction;
 import org.openstreetmap.josm.actions.UploadAction;
+import org.openstreetmap.josm.actions.WmsServerAction;
 import org.openstreetmap.josm.data.Preferences;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.projection.Epsg4263;
+import org.openstreetmap.josm.data.projection.Epsg4326;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.gui.MapFrame;
@@ -83,6 +84,6 @@
 
 	private OpenAction openAction;
-
 	private DownloadAction downloadAction;
+    private Action wmsServerAction;
 	
 	/**
@@ -101,5 +102,6 @@
 		downloadAction = new DownloadAction();
 		Action uploadAction = new UploadAction();
-		openAction = new OpenAction();
+		wmsServerAction = new WmsServerAction();
+        openAction = new OpenAction();
 		Action saveAction = new SaveAction();
 		Action gpxExportAction = new GpxExportAction(null);
@@ -124,9 +126,11 @@
 
 		
-		JMenu connectionMenu = new JMenu("Connection");
-		connectionMenu.setMnemonic('C');
-		connectionMenu.add(downloadAction);
-		connectionMenu.add(uploadAction);
-		mainMenu.add(connectionMenu);
+		JMenu layerMenu = new JMenu("Layer");
+		layerMenu.setMnemonic('L');
+		layerMenu.add(downloadAction);
+		layerMenu.add(uploadAction);
+        layerMenu.addSeparator();
+        //layerMenu.add(new JCheckBoxMenuItem(wmsServerAction));
+		mainMenu.add(layerMenu);
 		
 		JMenu editMenu = new JMenu("Edit");
@@ -149,4 +153,5 @@
 		toolBar.add(downloadAction);
 		toolBar.add(uploadAction);
+		//toolBar.add(new IconToggleButton(wmsServerAction));
 		toolBar.addSeparator();
 		toolBar.add(openAction);
@@ -242,5 +247,5 @@
 			e.printStackTrace();
 			JOptionPane.showMessageDialog(null, "The projection could not be read from preferences. Using EPSG:4263.");
-			proj = new Epsg4263();
+			proj = new Epsg4326();
 		}
 		
@@ -320,4 +325,8 @@
 			mapFrame.setVisible(true);
 		}
+        //TODO: This is really hacky to unselect the action when the layer gets
+        // deleted. The whole mapView/mapFrame/layer concept needs refactoring!
+		if (mapFrame == null && (Boolean)wmsServerAction.getValue(Action.SELECTED_KEY))
+			wmsServerAction.putValue(Action.SELECTED_KEY, false);
 	}
 	/**
Index: /src/org/openstreetmap/josm/actions/DiskAccessAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 78)
+++ /src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 79)
@@ -29,5 +29,5 @@
 	protected boolean isDataSetEmpty() {
 		for (OsmPrimitive osm : Main.main.ds.allNonDeletedPrimitives())
-			if (osm.id > 0)
+			if (!osm.isDeleted() || osm.id > 0)
 				return false;
 		return true;
Index: /src/org/openstreetmap/josm/actions/DownloadAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 78)
+++ /src/org/openstreetmap/josm/actions/DownloadAction.java	(revision 79)
@@ -356,14 +356,13 @@
 					closeDialog();
 					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, x.getMessage());
+					JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
 				} catch (JDOMException x) {
 					closeDialog();
 					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main, x.getMessage());
+					JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
 				} catch (FileNotFoundException x) {
 					closeDialog();
 					x.printStackTrace();
-					JOptionPane.showMessageDialog(Main.main,
-							"URL nicht gefunden: " + x.getMessage());
+					JOptionPane.showMessageDialog(Main.main, "URL not found: " + x.getMessage());
 				} catch (IOException x) {
 					closeDialog();
Index: /src/org/openstreetmap/josm/actions/GpxExportAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/GpxExportAction.java	(revision 78)
+++ /src/org/openstreetmap/josm/actions/GpxExportAction.java	(revision 79)
@@ -107,7 +107,7 @@
 		
 		Main.pref.put("lastAddAuthor", author.isSelected());
-		if (!authorName.getText().isEmpty())
+		if (authorName.getText().length() != 0)
 			Main.pref.put("lastAuthorName", authorName.getText());
-		if (!copyright.getText().isEmpty())
+		if (copyright.getText().length() != 0)
 			Main.pref.put("lastCopyright", copyright.getText());
 		
@@ -160,5 +160,5 @@
 				email.setText(b ? Main.pref.get("osm-server.username") : "");
 
-				boolean authorSet = !authorName.getText().isEmpty();
+				boolean authorSet = authorName.getText().length() != 0;
 				enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet);
 			}
@@ -168,5 +168,5 @@
 		KeyAdapter authorNameListener = new KeyAdapter(){
 					@Override public void keyReleased(KeyEvent e) {
-						boolean b = !authorName.getText().isEmpty() && author.isSelected();
+						boolean b = authorName.getText().length()!=0 && author.isSelected();
 						enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
 					}
@@ -193,5 +193,5 @@
 						break;
 					}
-					license += license.isEmpty() ? urls[i] : ", "+urls[i];
+					license += license.length()==0 ? urls[i] : ", "+urls[i];
 				}
 				copyright.setText(license);
@@ -212,10 +212,10 @@
 		warning.setText(enable ? warningGpl : "<html><font size='-2'>&nbsp;</html");
 
-		if (enable && copyrightYear.getText().isEmpty()) {
+		if (enable && copyrightYear.getText().length()==0) {
 			copyrightYear.setText(enable ? Integer.toString(Calendar.getInstance().get(Calendar.YEAR)) : "");
 		} else if (!enable)
 			copyrightYear.setText("");
 
-		if (enable && copyright.getText().isEmpty()) {
+		if (enable && copyright.getText().length()==0) {
 			copyright.setText(enable ? Main.pref.get("lastCopyright", "http://creativecommons.org/licenses/by-sa/2.5") : "");
 			copyright.setCaretPosition(0);
Index: /src/org/openstreetmap/josm/actions/OpenAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/OpenAction.java	(revision 78)
+++ /src/org/openstreetmap/josm/actions/OpenAction.java	(revision 79)
@@ -81,5 +81,5 @@
 						dataSet = OsmReader.parseDataSet(new FileReader(filename));
 					} catch (SAXException x) {
-						if (x.getMessage().equals("Unknown version: null")) {
+						if (x.getMessage().equals("Unknown version null")) {
 							int answer = JOptionPane.showConfirmDialog(Main.main, 
 									fn+" seems to be an old 0.2 API XML file.\n" +
@@ -112,8 +112,8 @@
 		} catch (SAXException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.main, x.getMessage());
+			JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
 		} catch (JDOMException x) {
 			x.printStackTrace();
-			JOptionPane.showMessageDialog(Main.main, x.getMessage());
+			JOptionPane.showMessageDialog(Main.main, "Error while parsing: "+x.getMessage());
 		} catch (IOException x) {
 			x.printStackTrace();
Index: /src/org/openstreetmap/josm/actions/WmsServerAction.java
===================================================================
--- /src/org/openstreetmap/josm/actions/WmsServerAction.java	(revision 79)
+++ /src/org/openstreetmap/josm/actions/WmsServerAction.java	(revision 79)
@@ -0,0 +1,48 @@
+package org.openstreetmap.josm.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import javax.swing.AbstractButton;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.WmsServerLayer;
+
+public class WmsServerAction extends JosmAction {
+
+    public WmsServerAction() {
+        super("Show background", "wmsserver", "Download and show landsat background images.", KeyEvent.VK_B);
+    }
+
+    public void actionPerformed(ActionEvent e) {
+    	JOptionPane.showMessageDialog(Main.main, "Not implemented yet.");
+    	if (1==1) return;
+        MapFrame mapFrame = Main.main.getMapFrame();
+        if (!((AbstractButton)e.getSource()).isSelected()) {
+            if (mapFrame != null) {
+                MapView mv = mapFrame.mapView;
+                for (Layer l : mv.getAllLayers()) {
+                    if (l instanceof WmsServerLayer) {
+                        if (mv.getAllLayers().size() == 1) {
+                            Main.main.setMapFrame(null);
+                            Main.main.ds = new DataSet();
+                        } else
+                            mv.removeLayer(l);
+                        return;
+                    }
+                }
+            }
+        } else {
+            WmsServerLayer layer = new WmsServerLayer(Main.pref.get("wmsServerBaseUrl", "http://wms.jpl.nasa.gov/wms.cgi?request=GetMap&width=512&height=512&layers=global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&"));
+            if (mapFrame == null)
+                Main.main.setMapFrame(new MapFrame(layer));
+            else
+                mapFrame.mapView.addLayer(layer);
+        }
+    }
+}
Index: /src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- /src/org/openstreetmap/josm/data/Preferences.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/Preferences.java	(revision 79)
@@ -135,5 +135,5 @@
 		properties.clear();
 		properties.put("laf", "javax.swing.plaf.metal.MetalLookAndFeel");
-		properties.put("projection", "org.openstreetmap.josm.data.projection.Epsg4263");
+		properties.put("projection", "org.openstreetmap.josm.data.projection.Epsg4326");
 		properties.put("osm-server.url", "http://www.openstreetmap.org/api");
 		properties.put("color.node", ColorHelper.color2html(Color.red));
Index: /src/org/openstreetmap/josm/data/coor/EastNorth.java
===================================================================
--- /src/org/openstreetmap/josm/data/coor/EastNorth.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/coor/EastNorth.java	(revision 79)
@@ -24,5 +24,5 @@
 	@Override
 	public String toString() {
-		return "(EastNorth e="+x+", n="+y+")";
+		return "EastNorth[e="+x+", n="+y+"]";
 	}
 }
Index: /src/org/openstreetmap/josm/data/coor/LatLon.java
===================================================================
--- /src/org/openstreetmap/josm/data/coor/LatLon.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/coor/LatLon.java	(revision 79)
@@ -41,3 +41,8 @@
 			lon() < -Projection.MAX_LON || lon() > Projection.MAX_LON;
 	}
+
+    @Override
+    public String toString() {
+        return "LatLon[lat="+lat()+",lon="+lon()+"]";
+    }
 }
Index: /src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java
===================================================================
--- /src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/osm/visitor/SelectionComponentVisitor.java	(revision 79)
@@ -38,7 +38,7 @@
 		if (name == null) {
 			if (ls.incomplete)
-				name = ""+ls.id;
+				name = ls.id == 0 ? "new" : ""+ls.id;
 			else
-				name = ls.id+" ("+ls.from.coor.lat()+","+ls.from.coor.lon()+") -> ("+ls.to.coor.lat()+","+ls.to.coor.lon()+")";
+				name = (ls.id==0?"":ls.id+" ")+"("+ls.from.coor.lat()+","+ls.from.coor.lon()+") -> ("+ls.to.coor.lat()+","+ls.to.coor.lon()+")";
 		}
 		icon = ImageProvider.get("data", "segment");
@@ -52,5 +52,5 @@
 		name = n.get("name");
 		if (name == null)
-			name = n.id+" ("+n.coor.lat()+","+n.coor.lon()+")";
+			name = (n.id==0?"":""+n.id)+" ("+n.coor.lat()+","+n.coor.lon()+")";
 		icon = ImageProvider.get("data", "node");
 	}
Index: c/org/openstreetmap/josm/data/projection/Epsg4263.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Epsg4263.java	(revision 78)
+++ 	(revision )
@@ -1,25 +1,0 @@
-package org.openstreetmap.josm.data.projection;
-
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.coor.EastNorth;
-
-/**
- * Directly use latitude / longitude values as x/y.
- *
- * @author imi
- */
-public class Epsg4263 implements Projection {
-
-	public EastNorth latlon2eastNorth(LatLon p) {
-		return new EastNorth(p.lon(), p.lat());
-	}
-
-	public LatLon eastNorth2latlon(EastNorth p) {
-		return new LatLon(p.north(), p.east());
-	}
-
-	@Override
-	public String toString() {
-		return "EPSG:4263";
-	}
-}
Index: /src/org/openstreetmap/josm/data/projection/Epsg4326.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Epsg4326.java	(revision 79)
+++ /src/org/openstreetmap/josm/data/projection/Epsg4326.java	(revision 79)
@@ -0,0 +1,29 @@
+package org.openstreetmap.josm.data.projection;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.coor.EastNorth;
+
+/**
+ * Directly use latitude / longitude values as x/y.
+ *
+ * @author imi
+ */
+public class Epsg4326 implements Projection {
+
+	public EastNorth latlon2eastNorth(LatLon p) {
+		return new EastNorth(p.lon(), p.lat());
+	}
+
+	public LatLon eastNorth2latlon(EastNorth p) {
+		return new LatLon(p.north(), p.east());
+	}
+
+	@Override
+	public String toString() {
+		return "EPSG:4326";
+	}
+
+    public String getCacheDirectoryName() {
+        return "epsg4326";
+    }
+}
Index: /src/org/openstreetmap/josm/data/projection/Mercator.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/projection/Mercator.java	(revision 79)
@@ -31,3 +31,7 @@
 		return "Mercator";
 	}
+
+    public String getCacheDirectoryName() {
+        return "mercator";
+    }
 }
Index: /src/org/openstreetmap/josm/data/projection/Projection.java
===================================================================
--- /src/org/openstreetmap/josm/data/projection/Projection.java	(revision 78)
+++ /src/org/openstreetmap/josm/data/projection/Projection.java	(revision 79)
@@ -20,5 +20,5 @@
 	 */
 	public static final Projection[] allProjections = new Projection[]{
-		new Epsg4263(),
+		new Epsg4326(),
 		new Mercator()
 	};
@@ -42,3 +42,8 @@
 	 */
 	String toString();
+    
+    /**
+     * Get a filename compatible string (for the cache directory)
+     */
+    String getCacheDirectoryName();
 }
Index: /src/org/openstreetmap/josm/gui/IconToggleButton.java
===================================================================
--- /src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/IconToggleButton.java	(revision 79)
@@ -5,5 +5,4 @@
 
 import javax.swing.Action;
-import javax.swing.JComponent;
 import javax.swing.JToggleButton;
 
@@ -19,5 +18,5 @@
 	 * Construct the toggle button with the given action.
 	 */
-	public IconToggleButton(JComponent acceleratorReceiver, Action action) {
+	public IconToggleButton(Action action) {
 		super(action);
 		setText(null);
Index: /src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/MapFrame.java	(revision 79)
@@ -68,12 +68,12 @@
 		// toolbar
 		toolBarActions.setFloatable(false);
-		toolBarActions.add(new IconToggleButton(this, new ZoomAction(this)));
+		toolBarActions.add(new IconToggleButton(new ZoomAction(this)));
 		final SelectionAction selectionAction = new SelectionAction(this);
-		toolBarActions.add(new IconToggleButton(this, selectionAction));
-		toolBarActions.add(new IconToggleButton(this, new MoveAction(this)));
-		toolBarActions.add(new IconToggleButton(this, new AddNodeAction(this)));
-		toolBarActions.add(new IconToggleButton(this, new AddLineSegmentAction(this)));
-		toolBarActions.add(new IconToggleButton(this, new AddWayAction(this, selectionAction)));
-		toolBarActions.add(new IconToggleButton(this, new DeleteAction(this)));
+		toolBarActions.add(new IconToggleButton(selectionAction));
+		toolBarActions.add(new IconToggleButton(new MoveAction(this)));
+		toolBarActions.add(new IconToggleButton(new AddNodeAction(this)));
+		toolBarActions.add(new IconToggleButton(new AddLineSegmentAction(this)));
+		toolBarActions.add(new IconToggleButton(new AddWayAction(this, selectionAction)));
+		toolBarActions.add(new IconToggleButton(new DeleteAction(this)));
 
 		// all map modes in one button group
@@ -86,5 +86,5 @@
 		// autoScale
 		toolBarActions.addSeparator();
-		final JToggleButton autoScaleButton = new IconToggleButton(this, new AutoScaleAction(this));
+		final JToggleButton autoScaleButton = new IconToggleButton(new AutoScaleAction(this));
 		toolBarActions.add(autoScaleButton);
 		autoScaleButton.setText(null);
@@ -111,5 +111,5 @@
 
 	private void addIconToggle(JPanel toggleDialogs, ToggleDialog dlg) {
-		toolBarActions.add(new IconToggleButton(this, dlg.action));
+        toolBarActions.add(new IconToggleButton(dlg.action));
 		toggleDialogs.add(dlg);
 	}
Index: /src/org/openstreetmap/josm/gui/MapView.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MapView.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/MapView.java	(revision 79)
@@ -20,4 +20,5 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.WmsServerLayer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer.ModifiedChangedListener;
 
@@ -108,5 +109,8 @@
 
 		// add as a new layer
-		layers.add(0,layer);
+        if (layer instanceof WmsServerLayer)
+            layers.add(layers.size(), layer);
+        else
+            layers.add(0, layer);
 
 		for (LayerChangeListener l : listeners)
Index: /src/org/openstreetmap/josm/gui/PreferenceDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/PreferenceDialog.java	(revision 79)
@@ -68,4 +68,5 @@
 				pwd = null;
 			Main.pref.put("osm-server.password", pwd);
+			Main.pref.put("wmsServerBaseUrl", wmsServerBaseUrl.getText());
 			Main.pref.put("csvImportString", csvImportString.getText());
 			Main.pref.put("drawRawGpsLines", drawRawGpsLines.isSelected());
@@ -106,9 +107,9 @@
 	 * ComboBox with all look and feels.
 	 */
-	JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels());
+    private JComboBox lafCombo = new JComboBox(UIManager.getInstalledLookAndFeels());
 	/**
 	 * Combobox with all projections available
 	 */
-	JComboBox projectionCombo = new JComboBox(Projection.allProjections);
+    private JComboBox projectionCombo = new JComboBox(Projection.allProjections);
 	/**
 	 * The main tab panel.
@@ -119,28 +120,32 @@
 	 * Editfield for the Base url to the REST API from OSM. 
 	 */
-	JTextField osmDataServer = new JTextField(20);
+    private JTextField osmDataServer = new JTextField(20);
 	/**
 	 * Editfield for the username to the OSM account.
 	 */
-	JTextField osmDataUsername = new JTextField(20);
+    private JTextField osmDataUsername = new JTextField(20);
 	/**
 	 * Passwordfield for the userpassword of the REST API.
 	 */
-	JPasswordField osmDataPassword = new JPasswordField(20);
+    private JPasswordField osmDataPassword = new JPasswordField(20);
+    /**
+     * Base url of the WMS server. Holds everything except the bbox= argument.
+     */
+	private JTextField wmsServerBaseUrl = new JTextField(20);
 	/**
 	 * Comma seperated import string specifier or <code>null</code> if the first
 	 * data line should be interpreted as one.
 	 */
-	JTextField csvImportString = new JTextField(20);
+    private JTextField csvImportString = new JTextField(20);
 	/**
 	 * The checkbox stating whether nodes should be merged together.
 	 */
-	JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");
+    private JCheckBox drawRawGpsLines = new JCheckBox("Draw lines between raw gps points.");
 	/**
 	 * The checkbox stating whether raw gps lines should be forced.
 	 */
-	JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported.");
-
-	JTable colors;
+    private JCheckBox forceRawGpsLines = new JCheckBox("Force lines if no line segments imported.");
+
+    private JTable colors;
 	
 	
@@ -199,5 +204,6 @@
 		osmDataUsername.setText(Main.pref.get("osm-server.username"));
 		osmDataPassword.setText(Main.pref.get("osm-server.password"));
-		csvImportString.setText(Main.pref.get("csvImportString"));
+        wmsServerBaseUrl.setText(Main.pref.get("wmsServerBaseUrl", "http://wms.jpl.nasa.gov/wms.cgi?request=GetMap&width=512&height=512&layers=global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&"));
+        csvImportString.setText(Main.pref.get("csvImportString"));
 		drawRawGpsLines.setSelected(Main.pref.getBoolean("drawRawGpsLines"));
 		forceRawGpsLines.setToolTipText("Force drawing of lines if the imported data contain no line information.");
@@ -258,4 +264,5 @@
 		osmDataUsername.setToolTipText("Login name (email) to the OSM account.");
 		osmDataPassword.setToolTipText("Login password to the OSM account. Leave blank to not store any password.");
+        wmsServerBaseUrl.setToolTipText("The base URL to the server retrieving WMS background pictures from.");
 		csvImportString.setToolTipText("<html>Import string specification. lat/lon and time are imported.<br>" +
 				"<b>lat</b>: The latitude coordinate<br>" +
@@ -297,4 +304,7 @@
 		warning.setFont(warning.getFont().deriveFont(Font.ITALIC));
 		con.add(warning, GBC.eop().fill(GBC.HORIZONTAL));
+		con.add(new JLabel("WMS server base url (everything except bbox-parameter)"), GBC.eol());
+		con.add(wmsServerBaseUrl, GBC.eop().fill(GBC.HORIZONTAL));
+		con.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL));
 		con.add(new JLabel("CSV import specification (empty: read from first line in data)"), GBC.eol());
 		con.add(csvImportString, GBC.eop().fill(GBC.HORIZONTAL));
Index: /src/org/openstreetmap/josm/gui/WorldChooser.java
===================================================================
--- /src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/WorldChooser.java	(revision 79)
@@ -76,4 +76,7 @@
 				return "WorldChooser";
 			}
+            public String getCacheDirectoryName() {
+                throw new UnsupportedOperationException();
+            }
 		};
 		setMinimumSize(new Dimension(350, 350/2));
Index: /src/org/openstreetmap/josm/gui/dialogs/LayerList.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/dialogs/LayerList.java	(revision 79)
@@ -12,4 +12,6 @@
 import java.util.Collection;
 
+import javax.swing.AbstractAction;
+import javax.swing.Action;
 import javax.swing.DefaultListCellRenderer;
 import javax.swing.DefaultListModel;
@@ -42,5 +44,54 @@
 public class LayerList extends ToggleDialog implements LayerChangeListener {
 
-	/**
+	public final static class DeleteLayerAction extends AbstractAction {
+
+        private final JList layers;
+        private final Layer layer;
+
+        public DeleteLayerAction(JList layers, Layer layer) {
+            super("Delete", ImageProvider.get("dialogs", "delete"));
+            putValue(SHORT_DESCRIPTION, "Delete the selected layer.");
+            this.layers = layers;
+            this.layer = layer;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+        	if (layers.getModel().getSize() == 1) {
+        		Main.main.setMapFrame(null);
+        		Main.main.ds = new DataSet();
+        	} else {
+        	    int sel = layers.getSelectedIndex();
+                if (layer != null)
+                    Main.main.getMapFrame().mapView.removeLayer(layer);
+                else
+                    Main.main.getMapFrame().mapView.removeLayer((Layer)layers.getSelectedValue());
+                if (sel >= layers.getModel().getSize())
+                    sel = layers.getModel().getSize()-1;
+                if (layers.getSelectedValue() == null)
+                    layers.setSelectedIndex(sel);
+        	}
+        }
+    }
+
+    public final static class ShowHideLayerAction extends AbstractAction {
+        private final Layer layer;
+        private final JList layers;
+
+        public ShowHideLayerAction(JList layers, Layer layer) {
+            super("Show/Hide", ImageProvider.get("dialogs", "showhide"));
+            putValue(SHORT_DESCRIPTION, "Toggle visible state of the selected layer.");
+            this.layer = layer;
+            this.layers = layers;
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            Layer l = layer == null ? (Layer)layers.getSelectedValue() : layer;
+            l.visible = !l.visible;
+        	Main.main.getMapFrame().mapView.repaint();
+        	layers.repaint();
+        }
+    }
+
+    /**
 	 * The data model for the list component.
 	 */
@@ -71,5 +122,5 @@
 	 * Button for delete layer.
 	 */
-	private JButton deleteButton = new JButton(ImageProvider.get("dialogs", "delete"));
+	private Action deleteAction = new DeleteLayerAction(layers, null);
 
 	/**
@@ -77,5 +128,5 @@
 	 */
 	public LayerList(MapFrame mapFrame) {
-		super("Layers", "List of all layers", "layerlist", "Open a list of all loaded layers.", "L", KeyEvent.VK_L);
+		super("Layers", "List of all layers", "layerlist", "Open a list of all loaded layers.", "L", KeyEvent.VK_L, "layerlist");
 		setPreferredSize(new Dimension(320,100));
 		add(new JScrollPane(layers), BorderLayout.CENTER);
@@ -117,5 +168,5 @@
 				int index = layers.locationToIndex(e.getPoint());
 				Layer layer = (Layer)layers.getModel().getElementAt(index);
-				LayerListPopup menu = new LayerListPopup(layer);
+				LayerListPopup menu = new LayerListPopup(layers, layer);
 				menu.show(LayerList.this, e.getX(), e.getY());
 			}
@@ -158,32 +209,11 @@
 		buttonPanel.add(downButton);
 		
-		JButton visible = new JButton(ImageProvider.get("dialogs", "showhide"));
-		visible.setToolTipText("Toggle visible state of the selected layer.");
-		visible.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				Layer l = (Layer)layers.getSelectedValue();
-				l.visible = !l.visible;
-				mapView.repaint();
-				layers.repaint();
-			}
-		});
-		buttonPanel.add(visible);
-
-		deleteButton.setToolTipText("Delete the selected layer.");
-		deleteButton.addActionListener(new ActionListener(){
-			public void actionPerformed(ActionEvent e) {
-				if (model.size() == 1) {
-					Main.main.setMapFrame(null);
-					Main.main.ds = new DataSet();
-				} else {
-					int sel = layers.getSelectedIndex();
-					mapView.removeLayer((Layer)layers.getSelectedValue());
-					if (sel >= model.getSize())
-						sel = model.getSize()-1;
-					layers.setSelectedIndex(sel);
-				}
-			}
-		});
-		buttonPanel.add(deleteButton);
+		JButton showHideButton = new JButton(new ShowHideLayerAction(layers, null));
+        showHideButton.setText("");
+        buttonPanel.add(showHideButton);
+		
+        JButton deleteButton = new JButton(deleteAction);
+        deleteButton.setText("");
+        buttonPanel.add(deleteButton);
 
 		mergeButton.setToolTipText("Merge the selected layer into the layer directly below.");
@@ -216,5 +246,5 @@
 		upButton.setEnabled(sel > 0);
 		downButton.setEnabled(sel < model.getSize()-1);
-		deleteButton.setEnabled(!model.isEmpty());
+		deleteAction.setEnabled(!model.isEmpty());
 	}
 
Index: /src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/dialogs/LayerListPopup.java	(revision 79)
@@ -6,8 +6,8 @@
 
 import javax.swing.JColorChooser;
+import javax.swing.JList;
 import javax.swing.JMenuItem;
 import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
-import javax.swing.JSeparator;
 
 import org.openstreetmap.josm.Main;
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.layer.RawGpsDataLayer;
+import org.openstreetmap.josm.gui.layer.WmsServerLayer;
 import org.openstreetmap.josm.tools.ColorHelper;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -25,10 +26,14 @@
 public class LayerListPopup extends JPopupMenu {
 
-	public LayerListPopup(final Layer layer) {
+	public LayerListPopup(final JList layers, final Layer layer) {
+        add(new LayerList.ShowHideLayerAction(layers, layer));
+        add(new LayerList.DeleteLayerAction(layers, layer));
+        addSeparator();
+        
 		if (layer instanceof OsmDataLayer)
 			add(new JMenuItem(new SaveAction()));
 
-		add(new JMenuItem(new GpxExportAction(layer)));
-		
+        if (!(layer instanceof WmsServerLayer))
+            add(new JMenuItem(new GpxExportAction(layer)));
 
 		if (layer instanceof RawGpsDataLayer) {
@@ -56,6 +61,7 @@
 		}
 
-		add(new JSeparator());
-		
+        if (!(layer instanceof WmsServerLayer))
+            addSeparator();
+
 		JMenuItem info = new JMenuItem("Info", ImageProvider.get("info"));
 		info.addActionListener(new ActionListener(){
Index: /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/dialogs/PropertiesDialog.java	(revision 79)
@@ -213,5 +213,5 @@
 	 */
 	public PropertiesDialog(MapFrame mapFrame) {
-		super("Properties", "Properties Dialog", "properties", "Property for selected objects.", "P", KeyEvent.VK_P);
+		super("Properties", "Properties Dialog", "properties", "Property for selected objects.", "P", KeyEvent.VK_P, "propertiesdialog");
 		mv = mapFrame.mapView;
 
Index: /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/dialogs/SelectionListDialog.java	(revision 79)
@@ -51,5 +51,5 @@
 	 */
 	public SelectionListDialog(MapFrame mapFrame) {
-		super("Current Selection", "Selection List", "selectionlist", "Open a selection list window.", "E", KeyEvent.VK_E);
+		super("Current Selection", "Selection List", "selectionlist", "Open a selection list window.", "E", KeyEvent.VK_E, "selectionlist");
 		setPreferredSize(new Dimension(320,150));
 		displaylist.setCellRenderer(new OsmPrimitivRenderer());
Index: /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 78)
+++ /src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 79)
@@ -2,8 +2,10 @@
 
 import java.awt.BorderLayout;
+import java.awt.EventQueue;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
 import javax.swing.AbstractButton;
+import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.JLabel;
@@ -11,4 +13,5 @@
 import javax.swing.KeyStroke;
 
+import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JosmAction;
 
@@ -29,12 +32,15 @@
 	 * Create a new ToggleDialog.
 	 * @param title The title of the dialog.
+     * @param prefName Name of the base preference setting string (prefix)
+     *      with the final . (e.g.: "layerlist.")
 	 */
-	public ToggleDialog(String title, String name, String iconName, String tooltip, String shortCutName, int shortCut) {
+	public ToggleDialog(String title, String name, String iconName, String tooltip, String shortCutName, int shortCut, final String prefName) {
 		action = new JosmAction(name, "dialogs/"+iconName, tooltip, "Alt-"+shortCutName, KeyStroke.getKeyStroke(shortCut, KeyEvent.ALT_MASK)){
 			public void actionPerformed(ActionEvent e) {
 				boolean show = !isVisible();
-				if (e.getSource() instanceof AbstractButton)
+				if (e != null && e.getSource() instanceof AbstractButton)
 					show = ((AbstractButton)e.getSource()).isSelected();
 				setVisible(show);
+                Main.pref.put(prefName+"visible", show);
 			}
 		};
@@ -44,4 +50,12 @@
 		setVisible(false);
 		setBorder(BorderFactory.createEtchedBorder());
+		if (Main.pref.getBoolean(prefName+"visible")) {
+		    EventQueue.invokeLater(new Runnable(){
+		        public void run() {
+		            action.putValue(Action.SELECTED_KEY, true);
+		            action.actionPerformed(null);
+		        }
+		    });
+        }
 	}
 }
Index: /src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java
===================================================================
--- /src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java	(revision 79)
+++ /src/org/openstreetmap/josm/gui/layer/WmsServerLayer.java	(revision 79)
@@ -0,0 +1,101 @@
+package org.openstreetmap.josm.gui.layer;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.TileCache;
+
+/**
+ * This is a layer that grabs the current screen from an WMS server. The data
+ * fetched this way is tiled and cached to the disc to reduce server load.
+ */
+public class WmsServerLayer extends Layer {
+
+	private static Icon icon = ImageProvider.get("layer/wms");
+
+	private final TileCache cache;
+
+	private final String url;
+
+
+	public WmsServerLayer(String url) {
+		super(url.indexOf('/') != -1 ? url.substring(url.indexOf('/')+1) : url);
+
+		// to calculate the world dimension, we assume that the projection does
+		// not have problems with translating longitude to a correct scale.
+		// Next to that, the projection must be linear dependend on the lat/lon
+		// unprojected scale.
+		if (Projection.MAX_LON != 180)
+			throw new IllegalArgumentException("Wrong longitude transformation for tile cache. Can't operate on "+Main.proj);
+
+		this.url = url;
+		cache = new TileCache(url);
+	}
+
+	@Override
+	public Icon getIcon() {
+		return icon;
+	}
+
+	@Override
+	public String getToolTipText() {
+		return "WMS layer: "+url;
+	}
+
+	@Override
+	public boolean isMergable(Layer other) {
+		return false;
+	}
+
+	@Override
+	public void mergeFrom(Layer from) {
+	}
+
+	@Override
+	public void paint(Graphics g, final MapView mv) {
+//		EastNorth max = mv.getEastNorth(mv.getWidth(),0);
+//		EastNorth min = mv.getEastNorth(0,mv.getHeight());
+//		double width = max.east() - min.east();
+//		double height = max.north() - min.north();
+//		double tilesX = mv.getWidth() / TileCache.TILESIZE;
+//		double tilesY = mv.getHeight() / TileCache.TILESIZE;
+
+		// getting zoom level
+		int zoom = 0;
+		for (double w = mv.getScale(); w <= TileCache.worldDimension; w *= 2)
+			zoom++;
+		LatLon oneTile = Main.proj.eastNorth2latlon(new EastNorth(
+				TileCache.TILESIZE * mv.getScale(),
+				TileCache.TILESIZE * mv.getScale()));
+		if (oneTile.lat() > Projection.MAX_LAT || oneTile.lon() > Projection.MAX_LON) {
+			// just display the whole world
+			Image img = cache.get(0,0);
+			Point scr1 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(Projection.MAX_LAT, -Projection.MAX_LON)));
+			Point scr2 = mv.getPoint(Main.proj.latlon2eastNorth(new LatLon(-Projection.MAX_LAT, Projection.MAX_LON)));
+			g.drawImage(img, scr1.x, scr1.y, scr2.x, scr2.y, 0, 0, TileCache.TILESIZE, TileCache.TILESIZE, null);
+		}
+
+//		TileCache.TileInformation info = TileCache.pos2tile(min, zoom);
+		//System.out.println(url+"bbox="+info.min.lon()+","+info.min.lat()+","+info.max.lon()+","+info.max.lat());
+	}
+
+	@Override
+	public void visitBoundingBox(BoundingXYVisitor v) {
+		// doesn't have a bounding box
+	}
+
+	@Override
+	public Object getInfoComponent() {
+		return getToolTipText();
+	}
+}
Index: /src/org/openstreetmap/josm/io/GpxWriter.java
===================================================================
--- /src/org/openstreetmap/josm/io/GpxWriter.java	(revision 78)
+++ /src/org/openstreetmap/josm/io/GpxWriter.java	(revision 79)
@@ -465,5 +465,5 @@
 				LatLon ll = p.latlon;
 				out.print("      <trkpt lat='"+ll.lat()+"' lon='"+ll.lon()+"'");
-				if (p.time != null && !p.time.isEmpty()) {
+				if (p.time != null && p.time.length()!=0) {
 					out.println(">");
 					out.println("        <time>"+p.time+"</time>");
Index: /src/org/openstreetmap/josm/io/OsmReader.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmReader.java	(revision 78)
+++ /src/org/openstreetmap/josm/io/OsmReader.java	(revision 79)
@@ -74,5 +74,5 @@
 					throw new SAXException("Unknown version.");
 				if (!"0.3".equals(atts.getValue("version")))
-					throw new SAXException("Unknown version: "+atts.getValue("version"));
+					throw new SAXException("Unknown version "+atts.getValue("version"));
 			} else if (qName.equals("node")) {
 				Node n = new Node(new LatLon(getDouble(atts, "lat"), getDouble(atts, "lon")));
@@ -93,4 +93,6 @@
 				if (current instanceof Way) {
 					long id = getLong(atts, "id");
+					if (id == 0)
+						throw new SAXException("Incomplete line segment with id=0");
 					LineSegment ls = lineSegments.get(id);
 					if (ls == null) {
@@ -105,4 +107,5 @@
 			}
 		} catch (NumberFormatException x) {
+            x.printStackTrace(); // SAXException does not chain correctly
 			throw new SAXException(x.getMessage(), x);
 		} catch (NullPointerException x) {
@@ -122,6 +125,8 @@
 	 * Read out the common attributes from atts and put them into this.current.
 	 */
-	private void readCommon(Attributes atts) {
+	private void readCommon(Attributes atts) throws SAXException {
 		current.id = getLong(atts, "id");
+		if (current.id == 0)
+			throw new SAXException("Illegal object with id=0");
 		String action = atts.getValue("action");
 		if ("delete".equals(action))
Index: /src/org/openstreetmap/josm/io/OsmServerWriter.java
===================================================================
--- /src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 78)
+++ /src/org/openstreetmap/josm/io/OsmServerWriter.java	(revision 79)
@@ -66,4 +66,5 @@
 	public void visit(Node n) {
 		if (n.id == 0 && !n.isDeleted()) {
+			n.put("created_by", "JOSM");
 			sendRequest("PUT", "node", n, true);
 		} else if (n.isDeleted()) {
@@ -80,4 +81,5 @@
 	public void visit(LineSegment ls) {
 		if (ls.id == 0 && !ls.isDeleted()) {
+			ls.put("created_by", "JOSM");
 			sendRequest("PUT", "segment", ls, true);
 		} else if (ls.isDeleted()) {
@@ -94,4 +96,5 @@
 	public void visit(Way w) {
 		if (w.id == 0 && !w.isDeleted()) {
+			w.put("created_by", "JOSM");
 			sendRequest("PUT", "way", w, true);
 		} else if (w.isDeleted()) {
Index: /src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- /src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 78)
+++ /src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 79)
@@ -4,4 +4,6 @@
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Toolkit;
 import java.awt.Transparency;
 import java.awt.image.BufferedImage;
@@ -37,5 +39,5 @@
 	 * The icon cache
 	 */
-	private static Map<URL, ImageIcon> cache = new HashMap<URL, ImageIcon>();
+	private static Map<URL, Image> cache = new HashMap<URL, Image>();
 	
 	/**
@@ -44,18 +46,19 @@
 	 * @param subdir	The position of the directory, e.g. "layer"
 	 * @param name		The icons name (without the ending of ".png")
-	 * @return	The requested ImageIcon.
+	 * @return The requested Image.
 	 */
 	public static ImageIcon get(String subdir, String name) {
 		if (subdir != "")
 			subdir += "/";
-		URL path = Main.class.getResource("/images/"+subdir+name+".png");
+        String ext = name.indexOf('.') != -1 ? "" : ".png";
+		URL path = Main.class.getResource("/images/"+subdir+name+ext);
 		if (path == null)
-			throw new NullPointerException("/images/"+subdir+name+".png not found");
-		ImageIcon icon = cache.get(path);
-		if (icon == null) {
-			icon = new ImageIcon(path);
-			cache.put(path, icon);
+			throw new NullPointerException("/images/"+subdir+name+ext+" not found");
+		Image img = cache.get(path);
+		if (img == null) {
+			img = Toolkit.getDefaultToolkit().createImage(path);
+			cache.put(path, img);
 		}
-		return icon;
+		return new ImageIcon(img);
 	}
 
Index: /src/org/openstreetmap/josm/tools/TileCache.java
===================================================================
--- /src/org/openstreetmap/josm/tools/TileCache.java	(revision 79)
+++ /src/org/openstreetmap/josm/tools/TileCache.java	(revision 79)
@@ -0,0 +1,205 @@
+package org.openstreetmap.josm.tools;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+
+/**
+ * A tile cache utility class to calculate tiles from lat/lon values.
+ * 
+ * One tile is a prerendered image of 512x512 pixels in size. The Zoom level of
+ * a tile means, how big is the partion of the world, this tile occupy. On Mercator,
+ * zoom=0 is exact the whole world, while zoom=1 is one quarter, zoom=2 is one of 
+ * sixteen and so on.
+ * 
+ * The tile identifier is an 32-bit integer whose bits are ordered in pairs of two.
+ * If bit0 (the LSB) is 0, then the tile is right of the equator (0°). If bit1 is 0, it
+ * is in the northern hemisphere. The next two bits representing the quarter within
+ * the first quarter, so bit2 equals to 0 means, it is in the right half of the
+ * quarter, represented by bit0 and bit1.
+ */
+public class TileCache {
+
+    public static final int TILESIZE = 512;
+    
+    /**
+     * This is the dimension of the world on x or y axis (both are the same).  Calculated in the constructor from the current projection, so that the  tiles are square.
+     */
+    public static final double worldDimension;
+    
+    static {
+        EastNorth en = Main.proj.latlon2eastNorth(new LatLon(0,180));
+        worldDimension = en.east();
+    }
+    
+    
+	public static class TileInformation {
+    	/**
+    	 * The encoded tile id for that point
+    	 */
+    	public final int tileId;
+    	/**
+    	 * Offset of the point within the tile (after projection)
+    	 */
+    	public final double offsetX, offsetY;
+    	/**
+    	 * OSM zoom factor (0 = earth, 1=quarter of earth, 2=sixteenth of earth...)
+    	 */
+    	public final int zoom;
+    	/**
+    	 * Projected point 
+    	 */
+    	public final EastNorth pos;
+    	/**
+    	 * Unprojected lower left corner of the tile
+    	 */
+    	public final LatLon min;
+    	/**
+    	 * Unprojected upper right corner of the tile
+    	 */
+    	public final LatLon max;
+    	
+    	public TileInformation(int id, double x, double y, int z, EastNorth p, LatLon mi, LatLon ma) {
+    		tileId = id; offsetX = x; offsetY = y; zoom = z; pos = p; min = mi; max = ma;
+    	}
+    }
+
+	private final static Image loading = ImageProvider.get("loading.jpg").getImage();
+    
+    private Map<Integer, Map<Integer, Image>> cache = new TreeMap<Integer, Map<Integer, Image>>();
+    private final String urlBase;
+
+    
+    private Vector<Integer> currentlyLoading = new Vector<Integer>();
+
+
+	public TileCache(String urlBase) {
+        this.urlBase = urlBase;
+	}
+    
+    
+    /**
+     * Get the tile's information where the coordinate is in.
+     */
+    public static TileInformation pos2tile(EastNorth pos, int zoom) {
+        int id = 0;
+        double pivotE = 0, pivotN = 0;
+        double size = worldDimension;
+        int bit = 1;
+        for (int i = 0; i < zoom; ++i) {
+            size /= 2;
+
+            if (pos.east() < pivotE) {
+                id |= bit;
+                pivotE -= size;
+            } else
+                pivotE += size;
+            bit *= 2;
+
+            if (pos.north() < pivotN) {
+                id |= bit;
+                pivotN -= size;
+            } else
+                pivotN += size;
+            bit *= 2;
+        }
+        return new TileCache.TileInformation(id, pos.east()-pivotE, pos.north()-pivotN, zoom, pos, Main.proj.eastNorth2latlon(new EastNorth(pivotE-size, pivotN-size)), Main.proj.eastNorth2latlon(new EastNorth(pivotE+size, pivotN+size)));
+    }
+
+    /**
+     * Get the surrounding bounds of the tile.
+     */
+    public static Bounds tile2pos(int tileId, int zoom) {
+        int id = 0;
+        double pivotE = 0, pivotN = 0;
+        double size = worldDimension;
+        int bit = 1;
+        for (int i = 0; i < zoom; ++i) {
+            size /= 2;
+            
+            if ((id | bit) != 0)
+                pivotE += size;
+            else
+                pivotE -= size;
+            bit *= 2;
+            
+            if ((id | bit) != 0)
+                pivotN += size;
+            else
+                pivotN -= size;
+            bit *= 2;
+        }
+        return new Bounds(
+                Main.proj.eastNorth2latlon(new EastNorth(pivotE-size, pivotN-size)),
+                Main.proj.eastNorth2latlon(new EastNorth(pivotE+size, pivotN+size)));
+    }
+
+    /**
+     * Get the image for the specified tile.
+     */
+    public synchronized Image get(final int tileId, final int zoom) {
+        final File cacheDir = new File(Main.pref.get("cache.directory", Preferences.getPreferencesDir()+"cache")+"/"+Main.proj.getCacheDirectoryName()+"/"+zoom);
+        if (!cache.containsKey(zoom)) {
+            HashMap<Integer, Image> map = new HashMap<Integer, Image>();
+            if (!cacheDir.exists())
+                cacheDir.mkdirs();
+            for (File f : cacheDir.listFiles())
+                map.put(Integer.parseInt(f.getName()), loading);
+            cache.put(zoom, map);
+        }
+        final Map<Integer, Image> map = cache.get(zoom);
+        Image img = map.get(tileId);
+        if (img == loading) {
+            // load from disk
+            System.out.println("loading from disk "+cacheDir.getPath()+"/"+tileId);
+            img = Toolkit.getDefaultToolkit().createImage(cacheDir.getPath()+"/"+tileId);
+            map.put(tileId, img);
+        } else if (img == null) {
+            img = loading;
+            if (!currentlyLoading.contains(tileId*256+zoom)) {
+                currentlyLoading.add(tileId*256+zoom);
+                // load from network
+                new Thread(){
+                    @Override
+                    public void run() {
+                        try {
+                            Bounds b = tile2pos(tileId, zoom);
+                            URL url = new URL(urlBase+"bbox="+b.min.lon()+","+b.min.lat()+","+b.max.lon()+","+b.max.lat());
+                            System.out.println("loading from net "+url);
+                            InputStream in = url.openStream();
+                            OutputStream out = new FileOutputStream(cacheDir+"/"+tileId);
+                            byte[] buf = new byte[8192];
+                            for (int read = in.read(buf); read > 0; read = in.read(buf))
+                                out.write(buf, 0, read);
+                            in.close();
+                            out.close();
+                            map.put(tileId, loading);
+                            currentlyLoading.remove(tileId*256+zoom);
+                            Main.main.repaint();
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }        
+                    }
+                }.start();
+            }
+        } else {
+            System.out.println("providing from cache "+img.getWidth(null));
+        }
+        System.out.println(img.getWidth(null));
+        return img;
+    }
+}
