← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~gamag/widelands/EditorUndo into lp:widelands

 

G. Margiani has proposed merging lp:~gamag/widelands/EditorUndo into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~gamag/widelands/EditorUndo/+merge/92957

Implements undo and redo functionality to the editor.
All tool except of set_starting_pos and make_infrastructure can be undone.
The implementation is done on tool level. Each tool saves what it does
and has a function to reset this changes.
-- 
https://code.launchpad.net/~gamag/widelands/EditorUndo/+merge/92957
Your team Widelands Developers is requested to review the proposed merge of lp:~gamag/widelands/EditorUndo into lp:widelands.
=== added file 'pics/editor_redo.png'
Binary files pics/editor_redo.png	1970-01-01 00:00:00 +0000 and pics/editor_redo.png	2012-02-14 11:56:48 +0000 differ
=== added file 'pics/editor_undo.png'
Binary files pics/editor_undo.png	1970-01-01 00:00:00 +0000 and pics/editor_undo.png	2012-02-14 11:56:48 +0000 differ
=== modified file 'src/editor/editorinteractive.cc'
--- src/editor/editorinteractive.cc	2011-12-07 22:32:39 +0000
+++ src/editor/editorinteractive.cc	2012-02-14 11:56:48 +0000
@@ -47,41 +47,51 @@
 using Widelands::Building;
 
 Editor_Interactive::Editor_Interactive(Widelands::Editor_Game_Base & e) :
-Interactive_Base(e, g_options.pull_section("global")),
-m_need_save     (false),
-m_realtime      (WLApplication::get()->get_time()),
+	Interactive_Base(e, g_options.pull_section("global")),
+	m_need_save(false),
+	m_realtime(WLApplication::get()->get_time()),
+	m_history(m_undo, m_redo),
 
 #define INIT_BUTTON(picture, name, tooltip)                         \
- TOOLBAR_BUTTON_COMMON_PARAMETERS(name),                                      \
- g_gr->get_picture(PicMod_Game, "pics/" picture ".png"),                      \
- tooltip                                                                      \
+	TOOLBAR_BUTTON_COMMON_PARAMETERS(name),                                      \
+	g_gr->get_picture(PicMod_Game, "pics/" picture ".png"),                      \
+	tooltip                                                                      \
 
-m_toggle_main_menu
-	(INIT_BUTTON
-	 	("menu_toggle_menu", "menu", _("Menu"))),
-m_toggle_tool_menu
-	(INIT_BUTTON
-	 	("editor_menu_toggle_tool_menu", "tools", _("Tools"))),
-m_toggle_toolsize_menu
-	(INIT_BUTTON
-	 	("editor_menu_set_toolsize_menu", "toolsize",
-	 	 _("Toolsize"))),
-m_toggle_minimap
-	(INIT_BUTTON
-	 	("menu_toggle_minimap", "minimap", _("Minimap"))),
-m_toggle_buildhelp
-	(INIT_BUTTON
-	 	("menu_toggle_buildhelp", "buildhelp", _("Buildhelp"))),
-m_toggle_player_menu
-	(INIT_BUTTON
-	 	("editor_menu_player_menu", "players", _("Players")))
-{
+	m_toggle_main_menu
+	(INIT_BUTTON
+	 ("menu_toggle_menu", "menu", _("Menu"))),
+	m_toggle_tool_menu
+	(INIT_BUTTON
+	 ("editor_menu_toggle_tool_menu", "tools", _("Tools"))),
+	m_toggle_toolsize_menu
+	(INIT_BUTTON
+	 ("editor_menu_set_toolsize_menu", "toolsize",
+	  _("Toolsize"))),
+	m_toggle_minimap
+	(INIT_BUTTON
+	 ("menu_toggle_minimap", "minimap", _("Minimap"))),
+	m_toggle_buildhelp
+	(INIT_BUTTON
+	 ("menu_toggle_buildhelp", "buildhelp", _("Buildhelp"))),
+	m_toggle_player_menu
+	(INIT_BUTTON
+	 ("editor_menu_player_menu", "players", _("Players"))),
+	m_undo
+	(INIT_BUTTON
+	 ("editor_undo", "undo", _("Undo"))),
+	m_redo
+	(INIT_BUTTON
+	 ("editor_redo", "redo", _("Redo"))) {
 	m_toggle_main_menu.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_mainmenu, this));
 	m_toggle_tool_menu.sigclicked.connect(boost::bind(&Editor_Interactive::tool_menu_btn, this));
 	m_toggle_toolsize_menu.sigclicked.connect(boost::bind(&Editor_Interactive::toolsize_menu_btn, this));
 	m_toggle_minimap.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_minimap, this));
 	m_toggle_buildhelp.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_buildhelp, this));
 	m_toggle_player_menu.sigclicked.connect(boost::bind(&Editor_Interactive::toggle_playermenu, this));
+	m_undo.sigclicked.connect(boost::bind(&Editor_History::undo_action, &m_history
+	                                     ));
+	m_redo.sigclicked.connect(boost::bind(&Editor_History::redo_action, &m_history
+	                                     ));
 
 	m_toolbar.set_layout_toplevel(true);
 	m_toolbar.add(&m_toggle_main_menu,       UI::Box::AlignLeft);
@@ -90,15 +100,20 @@
 	m_toolbar.add(&m_toggle_minimap,         UI::Box::AlignLeft);
 	m_toolbar.add(&m_toggle_buildhelp,       UI::Box::AlignLeft);
 	m_toolbar.add(&m_toggle_player_menu,     UI::Box::AlignLeft);
+	m_toolbar.add(&m_undo,                   UI::Box::AlignLeft);
+	m_toolbar.add(&m_redo,                   UI::Box::AlignLeft);
 	adjust_toolbar_position();
 
+	m_undo.set_enabled(false);
+	m_redo.set_enabled(false);
+
 #ifndef DEBUG
 	set_display_flag(Interactive_Base::dfDebug, false);
 #else
 	set_display_flag(Interactive_Base::dfDebug, true);
 #endif
 
-	fieldclicked.connect(boost::bind(&Editor_Interactive::map_clicked, this));
+	fieldclicked.connect(boost::bind(&Editor_Interactive::map_clicked, this, false));
 }
 
 
@@ -116,23 +131,23 @@
 			uint32_t w, h;
 			g_gr->get_picture_size(picid, w, h);
 			map.overlay_manager().register_overlay
-				(sp, picid, 8, Point(w / 2, STARTING_POS_HOTSPOT_Y));
+			(sp, picid, 8, Point(w / 2, STARTING_POS_HOTSPOT_Y));
 		}
 	}
 
 	//  Resources: we do not calculate default resources, therefore we do not
 	//  expect to meet them here.
-	Widelands::World const &       world           = map.world();
+	Widelands::World const    &    world           = map.world();
 	Overlay_Manager        &       overlay_manager = map.overlay_manager();
 	Widelands::Extent        const extent          = map.extent();
 	iterate_Map_FCoords(map, extent, fc) {
 		if (uint8_t const amount = fc.field->get_resources_amount()) {
 			std::string const & immname =
-				world.get_resource(fc.field->get_resources())->get_editor_pic
-					(amount);
+			    world.get_resource(fc.field->get_resources())->get_editor_pic
+			    (amount);
 			if (immname.size())
 				overlay_manager.register_overlay
-					(fc, g_gr->get_picture(PicMod_Menu, immname.c_str()), 4);
+				(fc, g_gr->get_picture(PicMod_Menu, immname.c_str()), 4);
 		}
 	}
 
@@ -148,28 +163,31 @@
 	// TODO: get rid of cleanup_for_load, it tends to be very messy
 	// Instead, delete and re-create the egbase.
 	egbase().cleanup_for_load(true, false);
+	m_history
+	.reset();
 
 	std::auto_ptr<Widelands::Map_Loader> const ml
-		(map.get_correct_loader(filename.c_str()));
+	(map.get_correct_loader(filename.c_str()));
 	if (not ml.get())
 		throw warning
-			(_("Unsupported format"),
-			 _
-			 	("Widelands could not load the file \"%s\". The file format seems "
-			 	 "to be incompatible."),
-			 filename.c_str());
+		(_("Unsupported format"),
+		 _
+		 ("Widelands could not load the file \"%s\". The file format seems "
+		  "to be incompatible."),
+		 filename.c_str());
 
 	UI::ProgressWindow loader_ui("pics/editor.jpg");
 	std::vector<std::string> tipstext;
 	tipstext.push_back("editor");
-	GameTips editortips (loader_ui, tipstext);
+	GameTips editortips(loader_ui, tipstext);
 	{
 		std::string const old_world_name = map.get_world_name();
 		ml->preload_map(true);
 		if (strcmp(map.get_world_name(), old_world_name.c_str()))
 			change_world();
 	}
-	{ //  Load all tribes into memory
+	{
+		//  Load all tribes into memory
 		std::vector<std::string> tribenames;
 		Widelands::Tribe_Descr::get_all_tribenames(tribenames);
 		container_iterate_const(std::vector<std::string>, tribenames, i) {
@@ -179,14 +197,14 @@
 	}
 
 	// Create the players. TODO SirVer this must be managed better
-	loader_ui.step (_("Creating players"));
+	loader_ui.step(_("Creating players"));
 	iterate_player_numbers(p, map.get_nrplayers()) {
 		egbase().add_player
-			(p, 0, map.get_scenario_player_tribe(p),
-			 map.get_scenario_player_name(p));
+		(p, 0, map.get_scenario_player_tribe(p),
+		 map.get_scenario_player_name(p));
 	}
 
-	loader_ui.step (_("Loading world data"));
+	loader_ui.step(_("Loading world data"));
 	ml->load_world();
 	ml->load_map_complete(egbase(), true);
 	loader_ui.step(_("Loading graphics..."));
@@ -199,8 +217,7 @@
 
 
 /// Called just before the editor starts, after postload, init and gfxload.
-void Editor_Interactive::start()
-{
+void Editor_Interactive::start() {
 	// Run the editor initialization script, if any
 	try {
 		egbase().lua().run_script("map", "editor_init");
@@ -216,8 +233,7 @@
  *
  * Advance the timecounter and animate textures.
  */
-void Editor_Interactive::think()
-{
+void Editor_Interactive::think() {
 	Interactive_Base::think();
 
 	int32_t lasttime = m_realtime;
@@ -236,10 +252,10 @@
 void Editor_Interactive::exit() {
 	if (m_need_save) {
 		UI::WLMessageBox mmb
-			(this,
-			 _("Map unsaved"),
-			 _("The Map is unsaved, do you really want to quit?"),
-			 UI::WLMessageBox::YESNO);
+		(this,
+		 _("Map unsaved"),
+		 _("The Map is unsaved, do you really want to quit?"),
+		 UI::WLMessageBox::YESNO);
 		if (mmb.run() == 0)
 			return;
 	}
@@ -253,18 +269,19 @@
 		new Editor_Main_Menu(*this, m_mainmenu);
 }
 
-void Editor_Interactive::map_clicked() {
-	tools.current().handle_click(tools.use_tool, egbase().map(), get_sel_pos(), *this);
+void Editor_Interactive::map_clicked(bool draw) {
+	m_history
+	.do_action(tools.current(), tools.use_tool, egbase().map(),
+	           get_sel_pos(), *this, draw);
 	need_complete_redraw();
 	set_need_save(true);
 }
 
 /// Needed to get freehand painting tools (hold down mouse and move to edit).
-void Editor_Interactive::set_sel_pos(Widelands::Node_and_Triangle<> const sel)
-{
+void Editor_Interactive::set_sel_pos(Widelands::Node_and_Triangle<> const sel) {
 	bool const target_changed =
-		tools.current().operates_on_triangles() ?
-		sel.triangle != get_sel_pos().triangle : sel.node != get_sel_pos().node;
+	    tools.current().operates_on_triangles() ?
+	    sel.triangle != get_sel_pos().triangle : sel.node != get_sel_pos().node;
 	Interactive_Base::set_sel_pos(sel);
 	int32_t mask = SDL_BUTTON_LMASK;
 #ifdef __APPLE__
@@ -272,12 +289,10 @@
 	mask |= SDL_BUTTON_MMASK;
 #endif
 	if (target_changed and SDL_GetMouseState(0, 0) & mask)
-		map_clicked();
+		map_clicked(true);
 }
 
-
-void Editor_Interactive::toggle_buildhelp()
-{
+void Editor_Interactive::toggle_buildhelp() {
 	egbase().map().overlay_manager().toggle_buildhelp();
 }
 
@@ -317,59 +332,58 @@
 }
 
 
-bool Editor_Interactive::handle_key(bool const down, SDL_keysym const code)
-{
+bool Editor_Interactive::handle_key(bool const down, SDL_keysym const code) {
 	bool handled = Interactive_Base::handle_key(down, code);
 
 	if (down)
 		// only on down events
 		switch (code.sym) {
-		// Sel radius
+			// Sel radius
 		case SDLK_1:
-			set_sel_radius_and_update_menu (0);
+			set_sel_radius_and_update_menu(0);
 			handled = true;
 			break;
 		case SDLK_2:
-			set_sel_radius_and_update_menu (1);
+			set_sel_radius_and_update_menu(1);
 			handled = true;
 			break;
 		case SDLK_3:
-			set_sel_radius_and_update_menu (2);
+			set_sel_radius_and_update_menu(2);
 			handled = true;
 			break;
 		case SDLK_4:
-			set_sel_radius_and_update_menu (3);
+			set_sel_radius_and_update_menu(3);
 			handled = true;
 			break;
 		case SDLK_5:
-			set_sel_radius_and_update_menu (4);
+			set_sel_radius_and_update_menu(4);
 			handled = true;
 			break;
 		case SDLK_6:
-			set_sel_radius_and_update_menu (5);
+			set_sel_radius_and_update_menu(5);
 			handled = true;
 			break;
 		case SDLK_7:
-			set_sel_radius_and_update_menu (6);
+			set_sel_radius_and_update_menu(6);
 			handled = true;
 			break;
 		case SDLK_8:
-			set_sel_radius_and_update_menu (7);
+			set_sel_radius_and_update_menu(7);
 			handled = true;
 			break;
 		case SDLK_9:
-			set_sel_radius_and_update_menu (8);
+			set_sel_radius_and_update_menu(8);
 			handled = true;
 			break;
 		case SDLK_0:
-			set_sel_radius_and_update_menu (9);
+			set_sel_radius_and_update_menu(9);
 			handled = true;
 			break;
 
 		case SDLK_LSHIFT:
 		case SDLK_RSHIFT:
 			if (tools.use_tool == Editor_Tool::First)
-				select_tool (tools.current(), Editor_Tool::Second);
+				select_tool(tools.current(), Editor_Tool::Second);
 			handled = true;
 			break;
 
@@ -377,7 +391,7 @@
 		case SDLK_RALT:
 		case SDLK_MODE:
 			if (tools.use_tool == Editor_Tool::First)
-				select_tool (tools.current(), Editor_Tool::Third);
+				select_tool(tools.current(), Editor_Tool::Third);
 			handled = true;
 			break;
 
@@ -388,8 +402,8 @@
 
 		case SDLK_c:
 			set_display_flag
-				(Interactive_Base::dfShowCensus,
-				 !get_display_flag (Interactive_Base::dfShowCensus));
+			(Interactive_Base::dfShowCensus,
+			 !get_display_flag(Interactive_Base::dfShowCensus));
 			handled = true;
 			break;
 
@@ -404,7 +418,7 @@
 			break;
 
 		case SDLK_i:
-			select_tool (tools.info, Editor_Tool::First);
+			select_tool(tools.info, Editor_Tool::First);
 			handled = true;
 			break;
 
@@ -415,7 +429,7 @@
 
 		case SDLK_l:
 			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				new Main_Menu_Load_Map (*this);
+				new Main_Menu_Load_Map(*this);
 			handled = true;
 			break;
 
@@ -426,7 +440,7 @@
 
 		case SDLK_s:
 			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				new Main_Menu_Save_Map (*this);
+				new Main_Menu_Save_Map(*this);
 			handled = true;
 			break;
 
@@ -435,6 +449,21 @@
 			handled = true;
 			break;
 
+		case SDLK_z:
+			if ((code.mod & (KMOD_LCTRL | KMOD_RCTRL)) && (code.mod & (KMOD_LSHIFT | KMOD_RSHIFT)))
+				m_history
+				.redo_action();
+			else if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
+				m_history
+				.undo_action();
+			handled = true;
+			break;
+		case SDLK_y:
+			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
+				m_history
+				.redo_action();
+			handled = true;
+			break;
 		default:
 			break;
 
@@ -448,7 +477,7 @@
 		case SDLK_RALT:
 		case SDLK_MODE:
 			if (tools.use_tool != Editor_Tool::First)
-				select_tool (tools.current(), Editor_Tool::First);
+				select_tool(tools.current(), Editor_Tool::First);
 			handled = true;
 			break;
 		default:
@@ -460,9 +489,8 @@
 
 
 void Editor_Interactive::select_tool
-	(Editor_Tool & primary, Editor_Tool::Tool_Index const which)
-{
-	if (which == Editor_Tool::First and &primary != tools.current_pointer) {
+(Editor_Tool & primary, Editor_Tool::Tool_Index const which) {
+	if (which == Editor_Tool::First and & primary != tools.current_pointer) {
 		Widelands::Map & map = egbase().map();
 		//  A new tool has been selected. Remove all registered overlay callback
 		//  functions.
@@ -486,10 +514,9 @@
  *  data is a pointer to a tribe (for buildings)
  */
 void Editor_Interactive::reference_player_tribe
-	(Widelands::Player_Number const player, void const * const data)
-{
+(Widelands::Player_Number const player, void const * const data) {
 	assert(0 < player);
-	assert    (player <= egbase().map().get_nrplayers());
+	assert(player <= egbase().map().get_nrplayers());
 
 	Player_References r;
 	r.player = player;
@@ -500,15 +527,14 @@
 
 /// Unreference !once!, if referenced many times, this will leak a reference.
 void Editor_Interactive::unreference_player_tribe
-	(Widelands::Player_Number const player, void const * const data)
-{
+(Widelands::Player_Number const player, void const * const data) {
 	assert(player <= egbase().map().get_nrplayers());
 	assert(data);
 
 	std::vector<Player_References> & references = m_player_tribe_references;
 	std::vector<Player_References>::iterator it = references.begin();
 	std::vector<Player_References>::const_iterator references_end =
-		references.end();
+	    references.end();
 	if (player) {
 		for (; it < references_end; ++it)
 			if (it->player == player and it->object == data) {
@@ -525,10 +551,9 @@
 }
 
 bool Editor_Interactive::is_player_tribe_referenced
-	(Widelands::Player_Number const  player)
-{
+(Widelands::Player_Number const  player) {
 	assert(0 < player);
-	assert    (player <= egbase().map().get_nrplayers());
+	assert(player <= egbase().map().get_nrplayers());
 
 	for (uint32_t i = 0; i < m_player_tribe_references.size(); ++i)
 		if (m_player_tribe_references[i].player == player)
@@ -539,6 +564,8 @@
 
 
 void Editor_Interactive::change_world() {
+	m_history
+	.reset();
 	delete m_terrainmenu  .window;
 	delete m_immovablemenu.window;
 	delete m_bobmenu      .window;
@@ -550,8 +577,7 @@
  * Public static method to create an instance of the editor
  * and run it. This takes care of all the setup and teardown.
  */
-void Editor_Interactive::run_editor(std::string const & filename)
-{
+void Editor_Interactive::run_editor(std::string const & filename) {
 	Widelands::Editor_Game_Base editor(0);
 	Editor_Interactive eia(editor);
 	editor.set_ibase(&eia); // TODO get rid of this
@@ -559,7 +585,7 @@
 		UI::ProgressWindow loader_ui("pics/editor.jpg");
 		std::vector<std::string> tipstext;
 		tipstext.push_back("editor");
-		GameTips editortips (loader_ui, tipstext);
+		GameTips editortips(loader_ui, tipstext);
 		g_gr->flush(PicMod_Menu);
 
 		{
@@ -568,22 +594,22 @@
 			if (filename.empty()) {
 				loader_ui.step("Creating empty map...");
 				map.create_empty_map
-					(64, 64, "greenland", _("No Name"),
-					 g_options.pull_section("global").get_string
-						("realname", _("Unknown")));
+				(64, 64, "greenland", _("No Name"),
+				 g_options.pull_section("global").get_string
+				 ("realname", _("Unknown")));
 
-				{ //  Load all tribes into memory
+				{
+					//  Load all tribes into memory
 					std::vector<std::string> tribenames;
 					Widelands::Tribe_Descr::get_all_tribenames(tribenames);
-					container_iterate_const(std::vector<std::string>, tribenames, i)
-					{
+					container_iterate_const(std::vector<std::string>, tribenames, i) {
 						loader_ui.stepf(_("Loading tribe: %s"), i.current->c_str());
 						editor.manually_load_tribe(*i.current);
 					}
 				}
 				loader_ui.step(_("Loading graphics..."));
 				editor.load_graphics(loader_ui);
-			loader_ui.step(std::string());
+				loader_ui.step(std::string());
 			} else {
 				loader_ui.stepf("Loading map \"%s\"...", filename.c_str());
 				eia.load(filename);

=== modified file 'src/editor/editorinteractive.h'
--- src/editor/editorinteractive.h	2011-12-07 22:32:39 +0000
+++ src/editor/editorinteractive.h	2012-02-14 11:56:48 +0000
@@ -35,6 +35,7 @@
 #include "tools/editor_set_port_space_tool.h"
 #include "tools/editor_set_starting_pos_tool.h"
 #include "tools/editor_set_terrain_tool.h"
+#include "tools/editor_history.h"
 
 
 class Editor;
@@ -60,7 +61,7 @@
 	void start();
 	void think();
 
-	void map_clicked();
+	void map_clicked(bool draw = false);
 	virtual void set_sel_pos(Widelands::Node_and_Triangle<>);
 	void set_sel_radius_and_update_menu(uint32_t);
 
@@ -70,21 +71,21 @@
 	struct Tools {
 		Tools()
 			:
-			current_pointer   (&increase_height),
-			use_tool          (Editor_Tool::First),
-			increase_height   (decrease_height, set_height),
-			noise_height      (set_height),
-			place_immovable   (delete_immovable),
-			place_bob         (delete_bob),
+			current_pointer(&increase_height),
+			use_tool(Editor_Tool::First),
+			increase_height(decrease_height, set_height),
+			noise_height(set_height),
+			place_immovable(delete_immovable),
+			place_bob(delete_bob),
 			increase_resources(decrease_resources, set_resources),
-			set_port_space    (unset_port_space)
+			set_port_space(unset_port_space)
 
 		{}
-		Editor_Tool & current() const throw () {return *current_pointer;}
+		Editor_Tool & current() const throw() {return *current_pointer;}
 		typedef std::vector<Editor_Tool *> Tool_Vector;
 		typedef Tool_Vector::size_type Index;
 		//Tool_Vector                     tools;
-		Editor_Tool *                   current_pointer;
+		Editor_Tool          *          current_pointer;
 		Editor_Tool::Tool_Index         use_tool;
 		Editor_Info_Tool                info;
 		Editor_Set_Height_Tool          set_height;
@@ -108,7 +109,7 @@
 
 	void select_tool(Editor_Tool &, Editor_Tool::Tool_Index);
 
-	Widelands::Player * get_player() const throw () {return 0;}
+	Widelands::Player * get_player() const throw() {return 0;}
 
 	// action functions
 	void exit();
@@ -124,11 +125,11 @@
 	void change_world();
 
 private:
-	void toggle_buildhelp     ();
-	void tool_menu_btn        ();
-	void toolsize_menu_btn    ();
-	void toggle_mainmenu      ();
-	void toggle_playermenu    ();
+	void toggle_buildhelp();
+	void tool_menu_btn();
+	void toolsize_menu_btn();
+	void toggle_mainmenu();
+	void toggle_playermenu();
 
 	//  state variables
 	bool m_need_save;
@@ -140,6 +141,8 @@
 
 	int32_t m_realtime;
 
+	Editor_History m_history;
+
 	UI::UniqueWindow::Registry m_toolmenu;
 
 	UI::UniqueWindow::Registry m_toolsizemenu;
@@ -158,6 +161,8 @@
 	UI::Button m_toggle_minimap;
 	UI::Button m_toggle_buildhelp;
 	UI::Button m_toggle_player_menu;
+	UI::Button m_undo;
+	UI::Button m_redo;
 };
 
 #endif

=== added file 'src/editor/tools/editor_action_args.h'
--- src/editor/tools/editor_action_args.h	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_action_args.h	2012-02-14 11:56:48 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef EDITOR_ACTION_ARGS_H
+#define EDITOR_ACTION_ARGS_H
+
+#include <list>
+#include <string>
+
+#include "logic/bob.h"
+#include "logic/field.h"
+#include "interval.h"
+
+
+struct Editor_Interactive;
+struct Editor_Tool_Action;
+
+/// Class to save important and changeable properties of classes needed for actions
+// Implementations in editor_history.cc
+struct Editor_Action_Args {
+	uint32_t sel_radius;
+
+	int32_t change_by;                                              // resources, hight change tools
+	std::list<Widelands::Field::Height> origHights;                 // change hight tool
+	uint8_t cur_res, set_to;                                        // resources change tools
+	std::list<uint8_t> orgRes, orgResT;                             // resources set tool
+	std::list< const Widelands::Bob::Descr * > obob_type, nbob_type;// bob change tools
+	std::list<std::string> oimmov_types;                            // immovable change tools
+	std::list<int32_t> nimmov_types;                                // immovable change tools
+	interval<Widelands::Field::Height> m_interval;                  // noise hight tool
+	std::list<Widelands::Terrain_Index> terrainType, origTerrainType; // set terrain tool
+
+	std::list<Editor_Tool_Action *> draw_actions;                   // draw tool
+
+	Editor_Action_Args(Editor_Interactive & base);
+	~Editor_Action_Args();
+	uint32_t refcount;
+};
+
+#endif
\ No newline at end of file

=== modified file 'src/editor/tools/editor_decrease_height_tool.cc'
--- src/editor/tools/editor_decrease_height_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_decrease_height_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,17 +23,56 @@
 #include "editor_set_height_tool.h"
 #include "logic/map.h"
 #include "logic/field.h"
+#include "logic/mapregion.h"
 #include "editor/editorinteractive.h"
 
 /// Decreases the heights by a value. Chages surrounding nodes if necessary.
 int32_t Editor_Decrease_Height_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map & map,
+ Widelands::Node_and_Triangle<> center,
+ Editor_Interactive & parent,
+ Editor_Action_Args & args) {
+	if (args.origHights.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+		do args.origHights.push_back(mr.location().field->get_height());
+		while (mr.advance(map));
+	}
+
 	return
-		map.change_height
-			(Widelands::Area<Widelands::FCoords>
-			 	(map.get_fcoords(center.node), parent.get_sel_radius()),
-			 -m_change_by);
-}
+	    map.change_height
+	    (Widelands::Area<Widelands::FCoords>
+	     (map.get_fcoords(center.node), args.sel_radius),
+	     -args.change_by);
+}
+
+int32_t Editor_Decrease_Height_Tool::handle_undo_impl
+(Widelands::Map & map,
+ Widelands::Node_and_Triangle<> center,
+ Editor_Interactive & parent,
+ Editor_Action_Args & args) {
+	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+	std::list<Widelands::Field::Height>::iterator i = args.origHights.begin();
+
+	do {
+		mr.location().field->set_height(*i); i++;
+	} while (mr.advance(map));
+
+	map.recalc_for_field_area(Widelands::Area<Widelands::FCoords>
+	                          (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
+
+	return mr.radius() + 1;
+}
+
+Editor_Action_Args Editor_Decrease_Height_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.change_by = m_change_by;
+	return a;
+}
+
+

=== modified file 'src/editor/tools/editor_decrease_height_tool.h'
--- src/editor/tools/editor_decrease_height_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_decrease_height_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,13 +27,19 @@
 	Editor_Decrease_Height_Tool() : Editor_Tool(*this, *this), m_change_by(1) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_decrease_height.png";
 	}
 
-	int32_t get_change_by() const throw () {return m_change_by;}
-	void set_change_by(const int32_t n) throw () {m_change_by = n;}
+	int32_t get_change_by() const throw() {return m_change_by;}
+	void set_change_by(const int32_t n) throw() {m_change_by = n;}
 
 private:
 	int32_t m_change_by;

=== modified file 'src/editor/tools/editor_decrease_resources_tool.cc'
--- src/editor/tools/editor_decrease_resources_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_decrease_resources_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008, 2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2010-2014 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -35,49 +35,70 @@
  * there is not already another resource there.
 */
 int32_t Editor_Decrease_Resources_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args         &         args
+) {
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
 	do {
 		int32_t res    = mr.location().field->get_resources();
 		int32_t amount = mr.location().field->get_resources_amount();
 
-		amount -= m_change_by;
+		amount -= args.change_by;
 		if (amount < 0)
 			amount = 0;
 
+		args.orgResT.push_back(res);
+		args.orgRes.push_back(mr.location().field->get_resources_amount());
 
 		if
-			(res == m_cur_res
-			 and
-			 Editor_Change_Resource_Tool_Callback(mr.location(), &map, m_cur_res))
-		{
+		(res == args.cur_res
+		        and
+		        Editor_Change_Resource_Tool_Callback(mr.location(), &map, args.cur_res)) {
 			PictureID picid;
 			//  Ok, we're doing something. First remove the current overlays.
 			std::string str =
-				map.world().get_resource(res)->get_editor_pic
-					(mr.location().field->get_resources_amount());
+			    map.world().get_resource(res)->get_editor_pic
+			    (mr.location().field->get_resources_amount());
 			picid = g_gr->get_picture(PicMod_Menu, str.c_str());
 			map.overlay_manager().remove_overlay(mr.location(), picid);
 			if (!amount) {
 				mr.location().field->set_resources(0, 0);
 				mr.location().field->set_starting_res_amount(0);
 			} else {
-				mr.location().field->set_resources(m_cur_res, amount);
+				mr.location().field->set_resources(args.cur_res, amount);
 				mr.location().field->set_starting_res_amount(amount);
 				//  set new overlay
-				str = map.world().get_resource(m_cur_res)->get_editor_pic(amount);
+				str = map.world().get_resource(args.cur_res)->get_editor_pic(amount);
 				picid = g_gr->get_picture(PicMod_Menu, str.c_str());
 				map.overlay_manager().register_overlay(mr.location(), picid, 4);
 				map.recalc_for_field_area
-					(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
+
+int32_t Editor_Decrease_Resources_Tool::handle_undo_impl
+(Widelands::Map & map,
+ Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent,
+ Editor_Action_Args & args) {
+	return parent.tools.set_resources.handle_undo_impl(map, center, parent, args);
+	return 0;
+}
+
+Editor_Action_Args Editor_Decrease_Resources_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.change_by = m_change_by;
+	a.cur_res = m_cur_res;
+	return a;
+}
+
+
+

=== modified file 'src/editor/tools/editor_decrease_resources_tool.h'
--- src/editor/tools/editor_decrease_resources_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_decrease_resources_tool.h	2012-02-14 11:56:48 +0000
@@ -31,15 +31,21 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_decrease_resources.png";
 	}
 
-	int32_t get_change_by() const throw () {return m_change_by;}
-	void set_change_by(const int32_t n) throw () {m_change_by = n;}
+	int32_t get_change_by() const throw() {return m_change_by;}
+	void set_change_by(const int32_t n) throw() {m_change_by = n;}
 	Widelands::Resource_Index get_cur_res() const {return m_cur_res;}
-	void set_cur_res(Widelands::Resource_Index const res) throw () {
+	void set_cur_res(Widelands::Resource_Index const res) throw() {
 		m_cur_res = res;
 	}
 

=== modified file 'src/editor/tools/editor_delete_bob_tool.cc'
--- src/editor/tools/editor_delete_bob_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_delete_bob_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,18 +28,36 @@
  * Deletes the bob at the given location
 */
 int32_t Editor_Delete_Bob_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
 	Widelands::Editor_Game_Base & egbase = parent.egbase();
-	const int32_t radius = parent.get_sel_radius();
+	const int32_t radius = args.sel_radius;
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), radius));
-	do if (Widelands::Bob * const bob = mr.location().field->get_first_bob())
-		bob->remove(egbase);
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), radius));
+
+	do if (Widelands::Bob * const bob = mr.location().field->get_first_bob()) {
+			args.obob_type.push_back(&bob->descr());
+			bob->remove(egbase);
+		} else {
+			args.obob_type.push_back(NULL);
+		}
 	while (mr.advance(map));
 	return radius + 2;
 }
+
+int32_t Editor_Delete_Bob_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+
+	uint32_t ret = parent.tools.place_bob.handle_undo_impl(map, center, parent, args);
+	args.obob_type.clear();
+	return ret;
+}
+
+Editor_Action_Args Editor_Delete_Bob_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
+
+

=== modified file 'src/editor/tools/editor_delete_bob_tool.h'
--- src/editor/tools/editor_delete_bob_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_delete_bob_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 1012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,7 +27,13 @@
 	Editor_Delete_Bob_Tool() : Editor_Tool(*this, *this) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_delete.png";
 	}

=== modified file 'src/editor/tools/editor_delete_immovable_tool.cc'
--- src/editor/tools/editor_delete_immovable_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_delete_immovable_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,21 +30,37 @@
  * Deletes the immovable at the given location
 */
 int32_t Editor_Delete_Immovable_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args & args) {
 	Widelands::Editor_Game_Base & egbase = parent.egbase();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
 	do if
 		(upcast
-		 	(Widelands::Immovable,
-		 	 immovable,
-		 	 mr.location().field->get_immovable()))
-		immovable->remove(egbase); //  Delete no buildings or stuff.
+		        (Widelands::Immovable,
+		         immovable,
+		         mr.location().field->get_immovable())) {
+			args.oimmov_types.push_back(immovable->descr().name());
+			immovable->remove(egbase); //  Delete no buildings or stuff.
+		} else {
+			args.oimmov_types.push_back("");
+		}
 	while (mr.advance(map));
 	return mr.radius() + 2;
 }
+
+int32_t Editor_Delete_Immovable_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	Widelands::Editor_Game_Base & egbase = parent.egbase();
+	return parent.tools.place_immovable.handle_undo_impl(map, center, parent, args);
+}
+
+Editor_Action_Args Editor_Delete_Immovable_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
+

=== modified file 'src/editor/tools/editor_delete_immovable_tool.h'
--- src/editor/tools/editor_delete_immovable_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_delete_immovable_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,7 +27,13 @@
 	Editor_Delete_Immovable_Tool() : Editor_Tool(*this, *this) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_delete.png";
 	}

=== added file 'src/editor/tools/editor_draw_tool.cc'
--- src/editor/tools/editor_draw_tool.cc	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_draw_tool.cc	2012-02-14 11:56:48 +0000
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+
+#include "editor_draw_tool.h"
+
+#include "editor_history.h"
+#include "editor_action_args.h"
+
+
+/**
+ * \TODO Saving every action in a list isn't very efficient.
+ * A long list can take several seconds to undo/redo every action.
+ * If someone has a better idea how to do this, implement it!
+ */
+
+void Editor_Draw_Tool::add_action
+(Editor_Tool_Action ac, Editor_Action_Args & args) {
+	args.draw_actions.push_back(new Editor_Tool_Action(ac));
+}
+
+int32_t Editor_Draw_Tool::handle_click_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+
+	for (std::list<Editor_Tool_Action *>::iterator i = args.draw_actions.begin();
+	        i != args.draw_actions.end();
+	        i++) {
+		(*i)->tool.handle_click(
+		    static_cast<Editor_Tool::Tool_Index>((*i)->i), (*i)->map, (*i)->center, (*i)->parent, *((*i)->args));
+	}
+	return args.draw_actions.size();
+}
+
+int32_t Editor_Draw_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	for (std::list<Editor_Tool_Action *>::reverse_iterator i = args.draw_actions.rbegin();
+	        i != args.draw_actions.rend();
+	        i++) {
+		(*i)->tool.handle_undo(
+		    static_cast<Editor_Tool::Tool_Index>((*i)->i), (*i)->map, (*i)->center, (*i)->parent, *((*i)->args));
+	}
+	return args.draw_actions.size();
+}
+
+Editor_Action_Args Editor_Draw_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}

=== added file 'src/editor/tools/editor_draw_tool.h'
--- src/editor/tools/editor_draw_tool.h	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_draw_tool.h	2012-02-14 11:56:48 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef EDITOR_DRAW_TOOL_H
+#define EDITOR_DRAW_TOOL_H
+
+#include "editor_tool.h"
+#include "editor_tool_action.h"
+
+///  This is not a real editor tool. It serves to combine 'hold down mouse and move'
+///  tool actions in one class.
+struct Editor_Draw_Tool : public Editor_Tool {
+	Editor_Draw_Tool() : Editor_Tool(*this, *this) {}
+
+	int32_t handle_click_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
+	char const * get_sel_impl() const {
+		return "EDITOR_DRAW_TOOL";
+	}
+
+	void add_action(Editor_Tool_Action ac, Editor_Action_Args & args);
+
+};
+
+#endif
+

=== added file 'src/editor/tools/editor_history.cc'
--- src/editor/tools/editor_history.cc	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_history.cc	2012-02-14 11:56:48 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "editor_history.h"
+#include "editor_tool_action.h"
+#include "editor_action_args.h"
+#include "editor/editorinteractive.h"
+#include <string>
+
+// === Editor_Action_Args === //
+
+Editor_Action_Args::Editor_Action_Args(Editor_Interactive & base):
+	sel_radius(base.get_sel_radius()),
+	m_interval(0, 0),
+	refcount(0)
+{}
+
+Editor_Action_Args::~Editor_Action_Args() {
+	while (not draw_actions.empty()) {
+		delete draw_actions.back();
+		draw_actions.pop_back();
+	}
+	nbob_type.clear();
+	obob_type.clear();
+	nimmov_types.clear();
+	oimmov_types.clear();
+	orgRes.clear();
+	orgResT.clear();
+	origHights.clear();
+	origTerrainType.clear();
+	terrainType.clear();
+}
+
+// === Editor_History === //
+
+uint32_t Editor_History::undo_action() {
+	if (undo_stack.empty())
+		return 0;
+
+	Editor_Tool_Action uac = undo_stack.front();
+	undo_stack.pop_front();
+	redo_stack.push_front(uac);
+
+	m_undo_button.set_enabled(!undo_stack.empty());
+	m_redo_button.set_enabled(true);
+
+	return uac.tool.handle_undo(
+	           static_cast<Editor_Tool::Tool_Index>(uac.i), uac.map, uac.center, uac.parent, *uac.args);
+}
+
+uint32_t Editor_History::redo_action() {
+	if (redo_stack.empty())
+		return 0;
+
+	Editor_Tool_Action rac = redo_stack.front();
+	redo_stack.pop_front();
+	undo_stack.push_front(rac);
+
+	m_undo_button.set_enabled(true);
+	m_redo_button.set_enabled(!redo_stack.empty());
+
+	return rac.tool.handle_click(
+	           static_cast<Editor_Tool::Tool_Index>(rac.i), rac.map, rac.center, rac.parent, *rac.args);
+}
+
+uint32_t Editor_History::do_action(Editor_Tool & tool,
+                                   Editor_Tool::Tool_Index ind,
+                                   Widelands::Map & map,
+                                   const Widelands::Node_and_Triangle< Widelands::Coords > center,
+                                   Editor_Interactive & parent,
+                                   bool draw) {
+	Editor_Tool_Action ac(tool, static_cast<uint32_t>(ind), map, center, parent, tool.format_args(ind, parent));
+	if (draw && tool.is_unduable()) {
+		if (undo_stack.front().tool.get_sel_impl() != std::string(m_draw_tool.get_sel_impl())) {
+			Editor_Tool_Action da(m_draw_tool, Editor_Tool::First,
+			                      map, center, parent,
+			                      m_draw_tool.format_args(Editor_Tool::First, parent));
+			m_draw_tool.add_action(undo_stack.front(), *da.args);
+			undo_stack.pop_front();
+			undo_stack.push_front(da);
+		}
+		dynamic_cast<Editor_Draw_Tool *>(&(undo_stack.front().tool))->add_action(ac, *undo_stack.front().args);
+	} else if (tool.is_unduable()) {
+		redo_stack.clear();
+		undo_stack.push_front(ac);
+		m_undo_button.set_enabled(true);
+		m_redo_button.set_enabled(false);
+	}
+	return tool.handle_click(ind, map, center, parent, *ac.args);
+}
+
+
+void Editor_History::reset() {
+	undo_stack.clear();
+	redo_stack.clear();
+	m_undo_button.set_enabled(false);
+	m_redo_button.set_enabled(false);
+}
+

=== added file 'src/editor/tools/editor_history.h'
--- src/editor/tools/editor_history.h	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_history.h	2012-02-14 11:56:48 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef EDITOR_HISTORY_H
+#define EDITOR_HISTORY_H
+
+#include <deque>
+
+#include "editor_tool.h"
+#include "editor_draw_tool.h"
+
+//struct Editor_Action_Args;
+struct Editor_Interactive;
+namespace UI { struct Button; }
+
+/**
+ * The all actions done with an editor tool are saved on a stack to
+ * provide undo / redo functionality.
+ * Do all tool action you want to make "undoable" using this class.
+ */
+struct Editor_History {
+
+	Editor_History(UI::Button & undo, UI::Button & redo): m_undo_button(undo), m_redo_button(redo) {};
+
+	uint32_t do_action(Editor_Tool & tool, Editor_Tool::Tool_Index ind, Widelands::Map & map,
+	                   Widelands::Node_and_Triangle<> const center, Editor_Interactive & parent, bool draw = false);
+	uint32_t undo_action();
+	uint32_t redo_action();
+
+	/// Must be called after every change of map, world, or ... to avoid undo errors
+	void reset();
+
+private:
+
+	UI::Button & m_undo_button;
+	UI::Button & m_redo_button;
+
+	Editor_Draw_Tool m_draw_tool;
+
+	std::deque<Editor_Tool_Action> undo_stack;
+	std::deque<Editor_Tool_Action> redo_stack;
+
+};
+
+
+
+#endif
+

=== modified file 'src/editor/tools/editor_increase_height_tool.cc'
--- src/editor/tools/editor_increase_height_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_increase_height_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -21,18 +21,42 @@
 
 #include "logic/map.h"
 #include "logic/field.h"
+#include "logic/mapregion.h"
 #include "editor/editorinteractive.h"
 
-
 /// Increases the heights by a value. Chages surrounding nodes if necessary.
 int32_t Editor_Increase_Height_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map & map,
+ Widelands::Node_and_Triangle<> center,
+ Editor_Interactive & parent,
+ Editor_Action_Args & args) {
+	if (args.origHights.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+		do {
+			args.origHights.push_back(mr.location().field->get_height());
+		} while (mr.advance(map));
+	}
+
 	return
-		map.change_height
-			(Widelands::Area<Widelands::FCoords>
-			 	(map.get_fcoords(center.node), parent.get_sel_radius()),
-			 m_change_by);
-}
+	    map.change_height
+	    (Widelands::Area<Widelands::FCoords>
+	     (map.get_fcoords(center.node), args.sel_radius),
+	     args.change_by);
+}
+
+int32_t Editor_Increase_Height_Tool::handle_undo_impl
+(Widelands::Map & map,
+ Widelands::Node_and_Triangle<> center,
+ Editor_Interactive & parent,
+ Editor_Action_Args & args) {
+	return m_decrease_tool.handle_undo_impl(map, center, parent, args);
+}
+
+Editor_Action_Args Editor_Increase_Height_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.change_by = m_change_by;
+	return a;
+}
\ No newline at end of file

=== modified file 'src/editor/tools/editor_increase_height_tool.h'
--- src/editor/tools/editor_increase_height_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_increase_height_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,8 +26,8 @@
 ///  Increases the height of a field by a value.
 struct Editor_Increase_Height_Tool : public Editor_Tool {
 	Editor_Increase_Height_Tool
-		(Editor_Decrease_Height_Tool & the_decrease_tool,
-		 Editor_Set_Height_Tool      & the_set_tool)
+	(Editor_Decrease_Height_Tool & the_decrease_tool,
+	 Editor_Set_Height_Tool    &   the_set_tool)
 		:
 		Editor_Tool(the_decrease_tool, the_set_tool),
 		m_decrease_tool(the_decrease_tool), m_set_tool(the_set_tool),
@@ -35,22 +35,28 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_increase_height.png";
 	}
 
-	int32_t get_change_by() const throw () {return m_change_by;}
-	void set_change_by(const int32_t n) throw () {m_change_by = n;}
+	int32_t get_change_by() const throw() {return m_change_by;}
+	void set_change_by(const int32_t n) throw() {m_change_by = n;}
 
 	Editor_Decrease_Height_Tool & decrease_tool() const {
 		return m_decrease_tool;
 	}
-	Editor_Set_Height_Tool      & set_tool     () const {return m_set_tool;}
+	Editor_Set_Height_Tool    &   set_tool() const {return m_set_tool;}
 
 private:
 	Editor_Decrease_Height_Tool & m_decrease_tool;
-	Editor_Set_Height_Tool      & m_set_tool;
+	Editor_Set_Height_Tool    &   m_set_tool;
 	int32_t                           m_change_by;
 };
 

=== modified file 'src/editor/tools/editor_increase_resources_tool.cc'
--- src/editor/tools/editor_increase_resources_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_increase_resources_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008, 2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2010, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,12 +30,11 @@
 using Widelands::TCoords;
 
 int32_t Editor_Change_Resource_Tool_Callback
-	(TCoords<Widelands::FCoords> const c,
-	 void                      * const data,
-	 int32_t                     const curres)
-{
+(TCoords<Widelands::FCoords> const c,
+ void            *           const data,
+ int32_t                     const curres) {
 	assert(data);
-	Widelands::Map   & map   = *static_cast<Widelands::Map *>(data);
+	Widelands::Map  &  map   = *static_cast<Widelands::Map *>(data);
 	Widelands::World & world = map.world();
 	Widelands::FCoords f(c, &map[c]);
 
@@ -68,60 +67,75 @@
 ===========
 Editor_Increase_Resources_Tool::handle_click_impl()
 
-decrease the resources of the current field by one if
+increase the resources of the current field by one if
 there is not already another resource there.
 ===========
 */
 int32_t Editor_Increase_Resources_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args         &         args) {
 	Widelands::World const & world = map.world();
 	Overlay_Manager & overlay_manager = map.overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
 	do {
 		int32_t res        = mr.location().field->get_resources();
 		int32_t amount     = mr.location().field->get_resources_amount();
 		int32_t max_amount =
-			map.get_world()->get_resource(m_cur_res)->get_max_amount();
+		    map.get_world()->get_resource(args.cur_res)->get_max_amount();
 
-		amount += m_change_by;
+		amount += args.change_by;
 		if (amount > max_amount)
 			amount = max_amount;
 
+		args.orgResT.push_back(res);
+		args.orgRes.push_back(mr.location().field->get_resources_amount());
 
 		if
-			((res == m_cur_res or not res)
-			 and
-			 Editor_Change_Resource_Tool_Callback(mr.location(), &map, m_cur_res))
-		{
+		((res == args.cur_res or not res)
+		        and
+		        Editor_Change_Resource_Tool_Callback(mr.location(), &map, args.cur_res)) {
 			//  Ok, we're doing something. First remove the current overlays.
 			PictureID picid =
-				g_gr->get_picture
-					(PicMod_Menu,
-					 world.get_resource(res)->get_editor_pic
-					 	(mr.location().field->get_resources_amount()).c_str());
+			    g_gr->get_picture
+			    (PicMod_Menu,
+			     world.get_resource(res)->get_editor_pic
+			     (mr.location().field->get_resources_amount()).c_str());
 			overlay_manager.remove_overlay(mr.location(), picid);
 
 			if (not amount) {
 				mr.location().field->set_resources(0, 0);
 				mr.location().field->set_starting_res_amount(0);
 			} else {
-				mr.location().field->set_resources(m_cur_res, amount);
+				mr.location().field->set_resources(args.cur_res, amount);
 				mr.location().field->set_starting_res_amount(amount);
 				//  set new overlay
 				picid = g_gr->get_picture
-					(PicMod_Menu,
-					 world.get_resource(m_cur_res)->get_editor_pic(amount).c_str());
+				        (PicMod_Menu,
+				         world.get_resource(args.cur_res)->get_editor_pic(amount).c_str());
 				overlay_manager.register_overlay(mr.location(), picid, 4);
 				map.recalc_for_field_area
-					(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
+
+int32_t Editor_Increase_Resources_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	return m_set_tool.handle_undo_impl(map, center, parent, args);
+	return 0;
+}
+
+Editor_Action_Args Editor_Increase_Resources_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.change_by = m_change_by;
+	a.cur_res = m_cur_res;
+	return a;
+}

=== modified file 'src/editor/tools/editor_increase_resources_tool.h'
--- src/editor/tools/editor_increase_resources_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_increase_resources_tool.h	2012-02-14 11:56:48 +0000
@@ -27,8 +27,8 @@
 /// Increases the resources of a node by a value.
 struct Editor_Increase_Resources_Tool : public Editor_Tool {
 	Editor_Increase_Resources_Tool
-		(Editor_Decrease_Resources_Tool & the_decrease_tool,
-		 Editor_Set_Resources_Tool      & the_set_to_tool)
+	(Editor_Decrease_Resources_Tool & the_decrease_tool,
+	 Editor_Set_Resources_Tool    &   the_set_to_tool)
 		:
 		Editor_Tool(the_decrease_tool, the_set_to_tool),
 		m_decrease_tool(the_decrease_tool), m_set_tool(the_set_to_tool),
@@ -36,31 +36,37 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_increase_resources.png";
 	}
 
-	int32_t get_change_by() const throw () {return m_change_by;}
-	void set_change_by(const int32_t n) throw () {m_change_by = n;}
+	int32_t get_change_by() const throw() {return m_change_by;}
+	void set_change_by(const int32_t n) throw() {m_change_by = n;}
 	Widelands::Resource_Index get_cur_res() const {return m_cur_res;}
-	void set_cur_res(Widelands::Resource_Index const res) throw () {
+	void set_cur_res(Widelands::Resource_Index const res) throw() {
 		m_cur_res = res;
 	}
 
 	Editor_Decrease_Resources_Tool & decrease_tool() const {
 		return m_decrease_tool;
 	}
-	Editor_Set_Resources_Tool      & set_tool     () const {return m_set_tool;}
+	Editor_Set_Resources_Tool    &   set_tool() const {return m_set_tool;}
 
 private:
 	Editor_Decrease_Resources_Tool & m_decrease_tool;
-	Editor_Set_Resources_Tool      & m_set_tool;
+	Editor_Set_Resources_Tool    &   m_set_tool;
 	int32_t                              m_change_by;
 	Widelands::Resource_Index m_cur_res;
 };
 
 int32_t Editor_Change_Resource_Tool_Callback
-	(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
+(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
 
 #endif

=== modified file 'src/editor/tools/editor_info_tool.cc'
--- src/editor/tools/editor_info_tool.cc	2011-12-26 15:09:51 +0000
+++ src/editor/tools/editor_info_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -32,18 +32,18 @@
 
 /// Show a window with information about the pointed at node and triangle.
 int32_t Editor_Info_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args         &         args) {
 	Widelands::World const & world = map.world();
 	UI::Window * const w =
-		new UI::Window
-			(&parent, "field_information", 30, 30, 400, 200,
-			 _("Field Information"));
+	    new UI::Window
+	(&parent, "field_information", 30, 30, 400, 200,
+	 _("Field Information"));
 	UI::Multiline_Textarea * const multiline_textarea =
-		new UI::Multiline_Textarea
-			(w, 0, 0, w->get_inner_w(), w->get_inner_h());
+	    new UI::Multiline_Textarea
+	(w, 0, 0, w->get_inner_w(), w->get_inner_h());
 
 	Widelands::Field & f = map[center.node];
 
@@ -51,9 +51,9 @@
 	char buf1[1024];
 
 	snprintf
-		(buf1, sizeof(buf1),
-		 _("1) Node info\n Coordinates: (%i, %i)\n Height: %u\n Caps: "),
-		 center.node.x, center.node.y, f.get_height());
+	(buf1, sizeof(buf1),
+	 _("1) Node info\n Coordinates: (%i, %i)\n Height: %u\n Caps: "),
+	 center.node.x, center.node.y, f.get_height());
 	buf += buf1;
 	{
 		Widelands::NodeCaps const caps = f.nodecaps();
@@ -69,45 +69,45 @@
 		if (caps & Widelands::MOVECAPS_SWIM)  buf += _(" swim");
 	}
 	snprintf
-		(buf1, sizeof(buf1),
-		 _("\n Owned by %i\n Has base immovable: %s\n Has bobs: %s\n"),
-		 f.get_owned_by(),
-		 f.get_immovable() ? _("Yes") : _("No"),
-		 f.get_first_bob() ? _("Yes") : _("No"));
+	(buf1, sizeof(buf1),
+	 _("\n Owned by %i\n Has base immovable: %s\n Has bobs: %s\n"),
+	 f.get_owned_by(),
+	 f.get_immovable() ? _("Yes") : _("No"),
+	 f.get_first_bob() ? _("Yes") : _("No"));
 	buf += buf1;
 
 	buf += _("2) Terrain Info\n Name: ");
 	{
 		Widelands::Field         const & tf  = map[center.triangle];
 		Widelands::Terrain_Descr const & ter = world.terrain_descr
-			(center.triangle.t == Widelands::TCoords<>::D ?
-			 tf.terrain_d() : tf.terrain_r());
+		                                       (center.triangle.t == Widelands::TCoords<>::D ?
+		                                        tf.terrain_d() : tf.terrain_r());
 		buf += ter.descname();
 		snprintf
-			(buf1, sizeof(buf1), _("\n Texture Number: %i\n"), ter.get_texture());
+		(buf1, sizeof(buf1), _("\n Texture Number: %i\n"), ter.get_texture());
 		buf += buf1;
 	}
 
 	buf += _("4) Map Info\n Name: ");
 	buf += map.get_name();
 	snprintf
-		(buf1, sizeof(buf1),
-		 _("\n Size: %ix%i\n Author: "), map.get_width(), map.get_height());
+	(buf1, sizeof(buf1),
+	 _("\n Size: %ix%i\n Author: "), map.get_width(), map.get_height());
 	buf += buf1;
-	buf += map.get_author     ();
+	buf += map.get_author();
 	buf += _("\n Descr: ");
 	buf += map.get_description();
 	snprintf
-		(buf1, sizeof(buf1),
-		 _("\n Number of Players: %i\n"), map.get_nrplayers());
+	(buf1, sizeof(buf1),
+	 _("\n Number of Players: %i\n"), map.get_nrplayers());
 	buf += buf1;
 
 	buf += _("5) World Info\n Name: ");
-	buf += world.get_name  ();
+	buf += world.get_name();
 	buf += _("\n Author: ");
 	buf += world.get_author();
 	buf += _("\n Descr: ");
-	buf += world.get_descr ();
+	buf += world.get_descr();
 
 	multiline_textarea->set_text(buf.c_str());
 

=== modified file 'src/editor/tools/editor_info_tool.h'
--- src/editor/tools/editor_info_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_info_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -24,10 +24,11 @@
 
 /// A simple tool to show information about the clicked node.
 struct Editor_Info_Tool : public Editor_Tool {
-	Editor_Info_Tool() : Editor_Tool(*this, *this) {}
+	Editor_Info_Tool() : Editor_Tool(*this, *this, false) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
 	char const * get_sel_impl() const {return "pics/fsel_editor_info.png";}
 };
 

=== modified file 'src/editor/tools/editor_make_infrastructure_tool.cc'
--- src/editor/tools/editor_make_infrastructure_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_make_infrastructure_tool.cc	2012-02-14 11:56:48 +0000
@@ -31,13 +31,12 @@
  * Callback function to calculate correct overlays
  */
 int32_t Editor_Make_Infrastructure_Tool_Callback
-	(Widelands::TCoords<Widelands::FCoords> const c,
-	 void                                 *       data,
-	 int32_t                                const player)
-{
+(Widelands::TCoords<Widelands::FCoords> const c,
+ void                    *                    data,
+ int32_t                                const player) {
 	return
-		static_cast<Widelands::Editor_Game_Base const *>(data)->player(player)
-		.get_buildcaps(c);
+	    static_cast<Widelands::Editor_Game_Base const *>(data)->player(player)
+	    .get_buildcaps(c);
 }
 
 
@@ -48,12 +47,12 @@
  * Obviously, this function ignores the sel radius
 */
 int32_t Editor_Make_Infrastructure_Tool::handle_click_impl
-	(Widelands::Map               &,
-	 Widelands::Node_and_Triangle<> const,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map &,
+ Widelands::Node_and_Triangle<> const,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args         &         args) {
 	show_field_action
-		(&parent, parent.egbase().get_player(m_player), &m_registry);
+	(&parent, parent.egbase().get_player(m_player), &m_registry);
 
 	//  Not really needed, since Player Immovables are taken care of while
 	//  placing on map.

=== modified file 'src/editor/tools/editor_make_infrastructure_tool.h'
--- src/editor/tools/editor_make_infrastructure_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_make_infrastructure_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,17 +26,19 @@
 
 /**
  * This places immovables on the map
+ * \TODO Implement undo for this tool
 */
 struct Editor_Make_Infrastructure_Tool : public Editor_Tool {
-	Editor_Make_Infrastructure_Tool() : Editor_Tool(*this, *this), m_player(1) {}
+	Editor_Make_Infrastructure_Tool() : Editor_Tool(*this, *this, false) {}
 
-	void          set_player(Widelands::Player_Number const n) throw ()
+	void          set_player(Widelands::Player_Number const n) throw()
 	{m_player = n;}
-	Widelands::Player_Number get_player() const throw () {return m_player;}
+	Widelands::Player_Number get_player() const throw() {return m_player;}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
-	const char * get_sel_impl() const throw ()
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	const char * get_sel_impl() const throw()
 	{return "pics/fsel.png";} //  Standard sel icon, most complex tool of all
 
 private:
@@ -45,6 +47,6 @@
 };
 
 int32_t Editor_Make_Infrastructure_Tool_Callback
-	(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
+(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
 
 #endif

=== modified file 'src/editor/tools/editor_noise_height_tool.cc'
--- src/editor/tools/editor_noise_height_tool.cc	2011-12-26 09:52:54 +0000
+++ src/editor/tools/editor_noise_height_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -28,28 +28,52 @@
 
 /// Sets the heights to random values. Changes surrounding nodes if necessary.
 int32_t Editor_Noise_Height_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args & args) {
+	if (args.origHights.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+		do args.origHights.push_back(mr.location().field->get_height());
+		while (mr.advance(map));
+	}
+
 	uint32_t max = 0;
+
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
-	do
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
+	do {
 		max =
-			std::max
-				(max,
-				 map.set_height
-				 	(mr.location(),
-				 	 m_interval.min
-				 	 +
-				 	 static_cast<int32_t>
-				 	 	(static_cast<double>
-				 	 	 	(m_interval.max - m_interval.min + 1) * rand()
-				 	 	 /
-				 	 	 (RAND_MAX + 1.0))));
-	while (mr.advance(map));
+		    std::max
+		    (max,
+		     map.set_height
+		     (mr.location(),
+		      args.m_interval.min
+		      +
+		      static_cast<int32_t>
+		      (static_cast<double>
+		       (args.m_interval.max - args.m_interval.min + 1) * rand()
+		       /
+		       (RAND_MAX + 1.0)))
+		    );
+	} while (mr.advance(map));
 	return mr.radius() + max;
 }
+
+int32_t Editor_Noise_Height_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	return m_set_tool.handle_undo_impl(map, center, parent, args);
+}
+
+Editor_Action_Args Editor_Noise_Height_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.m_interval = m_interval;
+	return a;
+}
+

=== modified file 'src/editor/tools/editor_noise_height_tool.h'
--- src/editor/tools/editor_noise_height_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_noise_height_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,9 +25,9 @@
 /// Set the height of a node to a random value within a defined interval.
 struct Editor_Noise_Height_Tool : public Editor_Tool {
 	Editor_Noise_Height_Tool
-		(Editor_Set_Height_Tool & the_set_tool,
-		 const interval<Widelands::Field::Height> the_interval =
-		 interval<Widelands::Field::Height>(10, 14))
+	(Editor_Set_Height_Tool & the_set_tool,
+	 const interval<Widelands::Field::Height> the_interval =
+	     interval<Widelands::Field::Height>(10, 14))
 		:
 		Editor_Tool(the_set_tool, the_set_tool),
 		m_set_tool(the_set_tool),
@@ -35,7 +35,13 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_noise_height.png";
 	}
@@ -47,7 +53,7 @@
 		m_interval = i;
 	}
 
-	Editor_Set_Height_Tool & set_tool() const throw () {return m_set_tool;}
+	Editor_Set_Height_Tool & set_tool() const throw() {return m_set_tool;}
 
 private:
 	Editor_Set_Height_Tool & m_set_tool;

=== modified file 'src/editor/tools/editor_place_bob_tool.cc'
--- src/editor/tools/editor_place_bob_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_place_bob_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008, 2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2010-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -31,26 +31,75 @@
  * and places this on the current field
 */
 int32_t Editor_Place_Bob_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
-	Widelands::Editor_Game_Base & egbase = parent.egbase();
-	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
-	if (get_nr_enabled()) {
-		do {
-			Bob::Descr const & descr =
-				*map.world().get_bob_descr(get_random_enabled());
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent,
+ Editor_Action_Args & args) {
+
+	if (get_nr_enabled() && args.obob_type.empty()) {
+		Widelands::Editor_Game_Base & egbase = parent.egbase();
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius));
+		do {
+			Bob * const mbob = mr.location().field->get_first_bob();
+			args.obob_type.push_back((mbob ? &mbob->descr() : NULL));
+			args.nbob_type.push_back(map.world().get_bob_descr(get_random_enabled()));
+		} while (mr.advance(map));
+	}
+
+	if (not args.nbob_type.empty()) {
+		Widelands::Editor_Game_Base & egbase = parent.egbase();
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius));
+		std::list< const Bob::Descr * >::iterator i = args.nbob_type.begin();
+		do {
+			Bob::Descr const & descr = *(*i);
 			if (mr.location().field->nodecaps() & descr.movecaps()) {
 				if (Bob * const bob = mr.location().field->get_first_bob())
 					bob->remove(egbase); //  There is already a bob. Remove it.
 				descr.create(egbase, 0, mr.location());
 			}
-		} while (mr.advance(map));
-		return mr.radius() + 2;
-	} else
-		return mr.radius();
-}
+			i++;
+		} while (mr.advance(map));
+		return mr.radius() + 2;
+	} else
+		return 0;
+}
+
+int32_t Editor_Place_Bob_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	if (not args.nbob_type.empty()) {
+		Widelands::Editor_Game_Base & egbase = parent.egbase();
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius));
+		std::list< const Bob::Descr * >::iterator i = args.obob_type.begin();
+		do {
+			if (*i) {
+				Bob::Descr const & descr = *(*i);
+				if (mr.location().field->nodecaps() & descr.movecaps()) {
+					if (Bob * const bob = mr.location().field->get_first_bob())
+						bob->remove(egbase); //  There is already a bob. Remove it.
+					descr.create(egbase, 0, mr.location());
+				}
+			} else if (Bob * const bob = mr.location().field->get_first_bob()) {
+				bob->remove(egbase);
+			}
+			i++;
+		} while (mr.advance(map));
+		return mr.radius() + 2;
+	} else
+		return 0;
+}
+
+Editor_Action_Args Editor_Place_Bob_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
+
+

=== modified file 'src/editor/tools/editor_place_bob_tool.h'
--- src/editor/tools/editor_place_bob_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_place_bob_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,7 +30,13 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {return "pics/fsel_editor_place_bob.png";}
 };
 

=== modified file 'src/editor/tools/editor_place_immovable_tool.cc'
--- src/editor/tools/editor_place_immovable_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_place_immovable_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008, 2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2010-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,28 +25,81 @@
 #include "logic/immovable.h"
 #include "logic/mapregion.h"
 
+#include "upcast.h"
+
+#include <string>
+
 /**
  * Choses an object to place randomly from all enabled
  * and places this on the current field
 */
 int32_t Editor_Place_Immovable_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
-	const int32_t radius = parent.get_sel_radius();
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent, Editor_Action_Args & args) {
+	const int32_t radius = args.sel_radius;
 	if (not get_nr_enabled())
 		return radius;
 	Widelands::Editor_Game_Base & egbase = parent.egbase();
+	if (args.oimmov_types.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), radius));
+		do {
+			const Widelands::BaseImmovable * im = mr.location().field->get_immovable();
+			args.oimmov_types.push_back((im ? im->descr().name() : ""));
+			args.nimmov_types.push_back(get_random_enabled());
+		} while (mr.advance(map));
+	}
+
+	if (not args.nimmov_types.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), radius));
+		std::list<int32_t>::iterator i = args.nimmov_types.begin();
+		do {
+			if
+			(not mr.location().field->get_immovable()
+			        and
+			        mr.location().field->nodecaps() & Widelands::MOVECAPS_WALK)
+				egbase.create_immovable(mr.location(), *i, 0);
+			i++;
+		} while (mr.advance(map));
+	}
+	return radius + 2;
+}
+
+int32_t Editor_Place_Immovable_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	const int32_t radius = args.sel_radius;
+	if (args.oimmov_types.empty())
+		return radius;
+
+	Widelands::Editor_Game_Base & egbase = parent.egbase();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), radius));
-	do if
-		(not mr.location().field->get_immovable()
-		 and
-		 mr.location().field->nodecaps() & Widelands::MOVECAPS_WALK)
-		egbase.create_immovable(mr.location(), get_random_enabled(), 0);
-	while (mr.advance(map));
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), radius));
+	std::list<std::string>::iterator i = args.oimmov_types.begin();
+	do {
+		if (upcast(Widelands::Immovable, immovable,
+		           mr.location().field->get_immovable())) {
+			immovable->remove(egbase);
+		}
+		if (!i->empty())
+			egbase.create_immovable(mr.location(), *i, 0);
+
+		i++;
+	} while (mr.advance(map));
 	return radius + 2;
 }
+
+Editor_Action_Args Editor_Place_Immovable_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
+
+
+

=== modified file 'src/editor/tools/editor_place_immovable_tool.h'
--- src/editor/tools/editor_place_immovable_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_place_immovable_tool.h	2012-02-14 11:56:48 +0000
@@ -32,7 +32,13 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_place_immovable.png";
 	}

=== modified file 'src/editor/tools/editor_set_height_tool.cc'
--- src/editor/tools/editor_set_height_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_height_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,17 +22,55 @@
 #include "editor_increase_height_tool.h"
 #include "editor_decrease_height_tool.h"
 #include "logic/map.h"
+#include "logic/mapregion.h"
 #include "logic/field.h"
 #include "editor/editorinteractive.h"
 
+
 int32_t Editor_Set_Height_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent, Editor_Action_Args & args) {
+	if (args.origHights.empty()) {
+		Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+		(map,
+		 Widelands::Area<Widelands::FCoords>
+		 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+		do args.origHights.push_back(mr.location().field->get_height());
+		while (mr.advance(map));
+	}
 	return
-		map.set_height
-			(Widelands::Area<Widelands::FCoords>
-			 	(map.get_fcoords(center.node), parent.get_sel_radius()),
-			 m_interval);
-}
+	    map.set_height
+	    (Widelands::Area<Widelands::FCoords>
+	     (map.get_fcoords(center.node), args.sel_radius),
+	     args.m_interval);
+}
+
+int32_t Editor_Set_Height_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 1));
+
+	std::list<Widelands::Field::Height>::iterator i = args.origHights.begin();
+
+	do {
+		mr.location().field->set_height(*i); i++;
+	} while (mr.advance(map));
+
+	map.recalc_for_field_area(Widelands::Area<Widelands::FCoords>
+	                          (map.get_fcoords(center.node), args.sel_radius + MAX_FIELD_HEIGHT / MAX_FIELD_HEIGHT_DIFF + 2));
+
+	return mr.radius() + 1;
+}
+
+Editor_Action_Args Editor_Set_Height_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.m_interval = m_interval;
+	return a;
+}
+
+
+

=== modified file 'src/editor/tools/editor_set_height_tool.h'
--- src/editor/tools/editor_set_height_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_height_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -31,12 +31,18 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_set_height.png";
 	}
 
-	interval<Widelands::Field::Height> get_interval() const throw () {
+	interval<Widelands::Field::Height> get_interval() const throw() {
 		return m_interval;
 	}
 	void set_interval(interval<Widelands::Field::Height> const i) {

=== modified file 'src/editor/tools/editor_set_origin_tool.cc'
--- src/editor/tools/editor_set_origin_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_origin_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 by the Widelands Development Team
+ * Copyright (C) 2009, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,17 +25,39 @@
 #include "wui/overlay_manager.h"
 
 int32_t Editor_Set_Origin_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       eia)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         eia, Editor_Action_Args & args) {
 	map.set_origin(center.node);
 	map.overlay_manager().reset();
 	eia.register_overlays();
 	eia.set_rel_viewpoint
-		(Point
-		 	(-(center.node.x * 2 + (center.node.y & 1)) * (TRIANGLE_WIDTH / 2),
-		 	 - center.node.y *                             TRIANGLE_HEIGHT),
-		 true);
-	return 0;
-}
+	(Point
+	 (-(center.node.x * 2 + (center.node.y & 1)) *(TRIANGLE_WIDTH / 2),
+	  - center.node.y *                             TRIANGLE_HEIGHT),
+	 true);
+	return 0;
+}
+
+int32_t Editor_Set_Origin_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	Widelands::Coords nc(map.get_width() - center.node.x,
+	                     map.get_height() - center.node.y);
+	map.set_origin(nc);
+	map.overlay_manager().reset();
+	parent.register_overlays();
+	parent.set_rel_viewpoint
+	(Point
+	 (- (nc.x * 2 + (nc.y & 1)) *(TRIANGLE_WIDTH / 2),
+	  - nc.y * TRIANGLE_HEIGHT),
+	 true);
+	return 0;
+}
+
+Editor_Action_Args Editor_Set_Origin_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
+
+
+

=== modified file 'src/editor/tools/editor_set_origin_tool.h'
--- src/editor/tools/editor_set_origin_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_origin_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 by the Widelands Development Team
+ * Copyright (C) 2009, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,7 +29,13 @@
 	Editor_Set_Origin_Tool() : Editor_Tool(*this, *this) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & eia, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {return "pics/fsel.png";}
 };
 

=== modified file 'src/editor/tools/editor_set_port_space_tool.cc'
--- src/editor/tools/editor_set_port_space_tool.cc	2011-12-07 22:32:39 +0000
+++ src/editor/tools/editor_set_port_space_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,13 +25,13 @@
 #include "logic/map.h"
 #include "logic/mapfringeregion.h"
 #include "wui/overlay_manager.h"
+#include <editor/editorinteractive.h>
 
 using namespace Widelands;
 
 /// static callback function for overlay calculation
 int32_t Editor_Tool_Set_Port_Space_Callback
-	(Widelands::TCoords<Widelands::FCoords> const c, void * const data, int32_t)
-{
+(Widelands::TCoords<Widelands::FCoords> const c, void * const data, int32_t) {
 	assert(data);
 	Map const & map = *static_cast<Map const *>(data);
 	NodeCaps const caps = c.field->nodecaps();
@@ -48,24 +48,23 @@
 
 
 Editor_Set_Port_Space_Tool::Editor_Set_Port_Space_Tool
-	(Editor_Unset_Port_Space_Tool & the_unset_tool)
-:
+(Editor_Unset_Port_Space_Tool & the_unset_tool)
+	:
 	Editor_Tool(the_unset_tool, *this),
 	m_unset_tool(the_unset_tool)
 {}
 
 
 Editor_Unset_Port_Space_Tool::Editor_Unset_Port_Space_Tool()
-:
+	:
 	Editor_Tool(*this, *this)
 {}
 
 
 int32_t Editor_Set_Port_Space_Tool::handle_click_impl
-	(Map & map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive &)
-{
+(Map & map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive &,  Editor_Action_Args &) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -81,11 +80,16 @@
 	return 0;
 }
 
+int32_t Editor_Set_Port_Space_Tool::handle_undo_impl
+(Map & map, Node_and_Triangle< Coords > center, Editor_Interactive & parent, Editor_Action_Args & args) {
+	return parent.tools.unset_port_space.handle_click_impl(map, center, parent, args);
+}
+
+
 int32_t Editor_Unset_Port_Space_Tool::handle_click_impl
-	(Map & map,
-	 Node_and_Triangle<> const center,
-	 Editor_Interactive &)
-{
+(Map & map,
+ Node_and_Triangle<> const center,
+ Editor_Interactive &, Editor_Action_Args &) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -101,3 +105,8 @@
 	}
 	return 0;
 }
+
+int32_t Editor_Unset_Port_Space_Tool::handle_undo_impl
+(Map & map, Node_and_Triangle< Coords > center, Editor_Interactive & parent, Editor_Action_Args & args) {
+	return parent.tools.set_port_space.handle_click_impl(map, center, parent, args);
+}

=== modified file 'src/editor/tools/editor_set_port_space_tool.h'
--- src/editor/tools/editor_set_port_space_tool.h	2011-12-07 22:32:39 +0000
+++ src/editor/tools/editor_set_port_space_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -32,7 +32,11 @@
 	Editor_Unset_Port_Space_Tool();
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
 	char const * get_sel_impl() const {return FSEL_EUPS_FILENAME;}
 };
 
@@ -42,7 +46,11 @@
 	Editor_Set_Port_Space_Tool(Editor_Unset_Port_Space_Tool &);
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
 	char const * get_sel_impl() const {return FSEL_ESPS_FILENAME;}
 
 private:
@@ -50,6 +58,6 @@
 };
 
 int32_t Editor_Tool_Set_Port_Space_Callback
-	(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
+(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
 
 #endif

=== modified file 'src/editor/tools/editor_set_resources_tool.cc'
--- src/editor/tools/editor_set_resources_tool.cc	2011-12-28 23:06:44 +0000
+++ src/editor/tools/editor_set_resources_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008, 2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2010, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -32,53 +32,114 @@
  * Sets the resources of the current to a fixed value
 */
 int32_t Editor_Set_Resources_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent, Editor_Action_Args & args) {
 	Widelands::World const & world = map.world();
 	Overlay_Manager & overlay_manager = map.overlay_manager();
 	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
-		(map,
-		 Widelands::Area<Widelands::FCoords>
-		 	(map.get_fcoords(center.node), parent.get_sel_radius()));
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
 	do {
 		int32_t res        = mr.location().field->get_resources();
-		int32_t amount     = m_set_to;
-		int32_t max_amount = world.get_resource(m_cur_res)->get_max_amount();
+		int32_t amount     = args.set_to;
+		int32_t max_amount = world.get_resource(args.cur_res)->get_max_amount();
 
 		if (amount < 0)
 			amount = 0;
 		if (amount > max_amount)
 			amount = max_amount;
 
-		if (Editor_Change_Resource_Tool_Callback(mr.location(), &map, m_cur_res))
-		{
+		args.orgResT.push_back(res);
+		args.orgRes.push_back(mr.location().field->get_resources_amount());
+
+		if (Editor_Change_Resource_Tool_Callback(mr.location(), &map, args.cur_res)) {
 			//  Ok, we're doing something. First remove the current overlays.
 			PictureID picid =
-				g_gr->get_picture
-					(PicMod_Menu,
-					 world.get_resource(res)->get_editor_pic
-					 	(mr.location().field->get_resources_amount()).c_str());
+			    g_gr->get_picture
+			    (PicMod_Menu,
+			     world.get_resource(res)->get_editor_pic
+			     (mr.location().field->get_resources_amount()).c_str());
 			overlay_manager.remove_overlay(mr.location(), picid);
 
 			if (not amount) {
 				mr.location().field->set_resources(0, 0);
 				mr.location().field->set_starting_res_amount(0);
 			} else {
-				mr.location().field->set_resources(m_cur_res, amount);
+				mr.location().field->set_resources(args.cur_res, amount);
 				mr.location().field->set_starting_res_amount(amount);
 				//  set new overlay
 				picid =
-					g_gr->get_picture
-						(PicMod_Menu,
-						 world.get_resource(m_cur_res)->get_editor_pic(amount)
-						 .c_str());
+				    g_gr->get_picture
+				    (PicMod_Menu,
+				     world.get_resource(args.cur_res)->get_editor_pic(amount)
+				     .c_str());
 				overlay_manager.register_overlay(mr.location(), picid, 4);
 				map.recalc_for_field_area
-					(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+				(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
 			}
 		}
 	} while (mr.advance(map));
 	return mr.radius();
 }
+
+int32_t Editor_Set_Resources_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	Widelands::World const & world = map.world();
+	Overlay_Manager & overlay_manager = map.overlay_manager();
+	Widelands::MapRegion<Widelands::Area<Widelands::FCoords> > mr
+	(map,
+	 Widelands::Area<Widelands::FCoords>
+	 (map.get_fcoords(center.node), args.sel_radius));
+	std::list<uint8_t>::iterator ir = args.orgRes.begin(), it = args.orgResT.begin();
+	do {
+		int32_t res        = mr.location().field->get_resources();
+		int32_t amount     = *ir;
+		int32_t max_amount = world.get_resource(args.cur_res)->get_max_amount();
+
+		if (amount < 0)
+			amount = 0;
+		if (amount > max_amount)
+			amount = max_amount;
+
+		PictureID picid =
+		    g_gr->get_picture
+		    (PicMod_Menu,
+		     world.get_resource(res)->get_editor_pic
+		     (mr.location().field->get_resources_amount()).c_str());
+		overlay_manager.remove_overlay(mr.location(), picid);
+
+		if (not amount) {
+			mr.location().field->set_resources(0, 0);
+			mr.location().field->set_starting_res_amount(0);
+		} else {
+			mr.location().field->set_resources(*it, amount);
+			mr.location().field->set_starting_res_amount(amount);
+			//  set new overlay
+			picid =
+			    g_gr->get_picture
+			    (PicMod_Menu,
+			     world.get_resource(*it)->get_editor_pic(amount)
+			     .c_str());
+			overlay_manager.register_overlay(mr.location(), picid, 4);
+			map.recalc_for_field_area
+			(Widelands::Area<Widelands::FCoords>(mr.location(), 0));
+		}
+		ir++;
+		it++;
+	} while (mr.advance(map));
+	args.orgRes.clear();
+	args.orgResT.clear();
+	return mr.radius();
+}
+
+Editor_Action_Args Editor_Set_Resources_Tool::format_args_impl(Editor_Interactive & parent) {
+	Editor_Action_Args a(parent);
+	a.cur_res = m_cur_res;
+	a.set_to = m_set_to;
+	return a;
+}
+
+

=== modified file 'src/editor/tools/editor_set_resources_tool.h'
--- src/editor/tools/editor_set_resources_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_resources_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -30,15 +30,21 @@
 	{}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {
 		return "pics/fsel_editor_set_resources.png";
 	}
 
-	uint8_t get_set_to() const throw () {return m_set_to;}
-	void set_set_to(uint8_t const n) throw () {m_set_to = n;}
-	Widelands::Resource_Index get_cur_res() const throw () {return m_cur_res;}
-	void set_cur_res(Widelands::Resource_Index const res) throw () {
+	uint8_t get_set_to() const throw() {return m_set_to;}
+	void set_set_to(uint8_t const n) throw() {m_set_to = n;}
+	Widelands::Resource_Index get_cur_res() const throw() {return m_cur_res;}
+	void set_cur_res(Widelands::Resource_Index const res) throw() {
 		m_cur_res = res;
 	}
 

=== modified file 'src/editor/tools/editor_set_starting_pos_tool.cc'
--- src/editor/tools/editor_set_starting_pos_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_starting_pos_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -33,8 +33,7 @@
  * static callback function for overlay calculation
  */
 int32_t Editor_Tool_Set_Starting_Pos_Callback
-	(Widelands::TCoords<Widelands::FCoords> const c, void * const data, int32_t)
-{
+(Widelands::TCoords<Widelands::FCoords> const c, void * const data, int32_t) {
 	assert(data);
 	Widelands::Map const & map = *static_cast<Widelands::Map const *>(data);
 
@@ -58,20 +57,17 @@
 	return 0;
 }
 
-
 Editor_Set_Starting_Pos_Tool::Editor_Set_Starting_Pos_Tool()
-: Editor_Tool(*this, *this), m_current_sel_pic(0)
-{
+	: Editor_Tool(*this, *this, false), m_current_sel_pic(0) {
 	m_current_player = 0;
 	strcpy(fsel_picsname, FSEL_PIC_FILENAME);
 }
 
 
 int32_t Editor_Set_Starting_Pos_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &)
-{
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive &, Editor_Action_Args &) {
 	assert(0 <= center.node.x);
 	assert(center.node.x < map.get_width());
 	assert(0 <= center.node.y);
@@ -96,16 +92,15 @@
 
 		//  check if field is valid
 		if
-			(Editor_Tool_Set_Starting_Pos_Callback
-			 	(map.get_fcoords(center.node), &map, 0))
-		{
+		(Editor_Tool_Set_Starting_Pos_Callback
+		        (map.get_fcoords(center.node), &map, 0)) {
 			Overlay_Manager & overlay_manager = map.overlay_manager();
 			//  remove old overlay if any
 			overlay_manager.remove_overlay(old_sp, picid);
 
 			//  add new overlay
 			overlay_manager.register_overlay
-				(center.node, picid, 8, Point(w / 2, STARTING_POS_HOTSPOT_Y));
+			(center.node, picid, 8, Point(w / 2, STARTING_POS_HOTSPOT_Y));
 
 			//  set new player pos
 			map.set_starting_pos(m_current_player, center.node);
@@ -116,9 +111,8 @@
 }
 
 Widelands::Player_Number Editor_Set_Starting_Pos_Tool::get_current_player
-	() const
-throw ()
-{
+() const
+throw() {
 	return m_current_player;
 }
 

=== modified file 'src/editor/tools/editor_set_starting_pos_tool.h'
--- src/editor/tools/editor_set_starting_pos_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_starting_pos_tool.h	2012-02-14 11:56:48 +0000
@@ -36,10 +36,10 @@
 	Editor_Set_Starting_Pos_Tool();
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &, Editor_Action_Args &);
 	char const * get_sel_impl() const {return m_current_sel_pic;}
 
-	Widelands::Player_Number get_current_player() const throw ();
+	Widelands::Player_Number get_current_player() const throw();
 	void set_current_player(int32_t);
 
 private:
@@ -48,6 +48,6 @@
 };
 
 int32_t Editor_Tool_Set_Starting_Pos_Callback
-	(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
+(Widelands::TCoords<Widelands::FCoords>, void *, int32_t);
 
 #endif

=== modified file 'src/editor/tools/editor_set_terrain_tool.cc'
--- src/editor/tools/editor_set_terrain_tool.cc	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_terrain_tool.cc	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -26,29 +26,69 @@
 using Widelands::TCoords;
 
 int32_t Editor_Set_Terrain_Tool::handle_click_impl
-	(Widelands::Map               &       map,
-	 Widelands::Node_and_Triangle<> const center,
-	 Editor_Interactive           &       parent)
-{
-	assert
-		(center.triangle.t == TCoords<>::D or center.triangle.t == TCoords<>::R);
-	uint16_t const radius = parent.get_sel_radius();
-	if (get_nr_enabled()) {
+(Widelands::Map           &           map,
+ Widelands::Node_and_Triangle<> const center,
+ Editor_Interactive         &         parent, Editor_Action_Args & args) {
+	assert
+	(center.triangle.t == TCoords<>::D or center.triangle.t == TCoords<>::R);
+	uint16_t const radius = args.sel_radius;
+	int32_t max = 0;
+
+	if (get_nr_enabled() && args.terrainType.empty()) {
+		Widelands::MapTriangleRegion<TCoords<Widelands::FCoords> > mr
+		(map, Widelands::Area<TCoords<Widelands::FCoords> >
+		 (TCoords<Widelands::FCoords>(Widelands::FCoords(map.get_fcoords(center.triangle)),
+		                              static_cast<TCoords<Widelands::FCoords>::TriangleIndex>(center.triangle.t)), radius));
+		do {
+			args.origTerrainType.push_back(
+			    (mr.location().t == TCoords<Widelands::FCoords>::D)
+			    ? mr.location().field->terrain_d() : mr.location().field->terrain_r());
+			args.terrainType.push_back(get_random_enabled());
+		} while (mr.advance(map));
+	}
+
+	if (not args.terrainType.empty()) {
+		Widelands::MapTriangleRegion<TCoords<Widelands::FCoords> > mr
+		(map, Widelands::Area<TCoords<Widelands::FCoords> >
+		 (TCoords<Widelands::FCoords>(Widelands::FCoords(map.get_fcoords(center.triangle)),
+		                              static_cast<TCoords<Widelands::FCoords>::TriangleIndex>(center.triangle.t)), radius));
+		std::list<Widelands::Terrain_Index>::iterator i = args.terrainType.begin();
+		do {
+			max = std::max
+			      (max, map.change_terrain(mr.location(), *i));
+			i++;
+		} while (mr.advance(map));
+	}
+	return radius + max;
+}
+
+int32_t Editor_Set_Terrain_Tool::handle_undo_impl
+(Widelands::Map & map, Widelands::Node_and_Triangle< Widelands::Coords > center,
+ Editor_Interactive & parent, Editor_Action_Args & args) {
+	assert
+	(center.triangle.t == TCoords<>::D or center.triangle.t == TCoords<>::R);
+	uint16_t const radius = args.sel_radius;
+	if (not args.terrainType.empty()) {
 		int32_t max = 0;
 		Widelands::MapTriangleRegion<TCoords<Widelands::FCoords> > mr
-			(map,
-			 Widelands::Area<TCoords<Widelands::FCoords> >
-			 	(TCoords<Widelands::FCoords>
-			 	 	(Widelands::FCoords(map.get_fcoords(center.triangle)),
-			 	 	 static_cast<TCoords<Widelands::FCoords>::TriangleIndex>
-			 	 	 	(center.triangle.t)),
-			 	 radius));
+		(map,
+		 Widelands::Area<TCoords<Widelands::FCoords> >
+		 (TCoords<Widelands::FCoords>
+		  (Widelands::FCoords(map.get_fcoords(center.triangle)),
+		   static_cast<TCoords<Widelands::FCoords>::TriangleIndex>
+		   (center.triangle.t)),
+		  radius));
+
+		std::list<Widelands::Terrain_Index>::iterator i = args.origTerrainType.begin();
 		do {
-			Widelands::Terrain_Index const new_terrain_index =
-				get_random_enabled();
-				max = std::max
-					(max, map.change_terrain(mr.location(), new_terrain_index));
+			max = std::max
+			      (max, map.change_terrain(mr.location(), *i));
+			i++;
 		} while (mr.advance(map));
 		return radius + max;
 	} else return radius;
 }
+
+Editor_Action_Args Editor_Set_Terrain_Tool::format_args_impl(Editor_Interactive & parent) {
+	return Editor_Tool::format_args_impl(parent);
+}
\ No newline at end of file

=== modified file 'src/editor/tools/editor_set_terrain_tool.h'
--- src/editor/tools/editor_set_terrain_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_set_terrain_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2008 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2008, 2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,9 +27,15 @@
 	Editor_Set_Terrain_Tool() : Editor_Tool(*this, *this) {}
 
 	int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &);
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	int32_t handle_undo_impl
+	(Widelands::Map & map, Widelands::Node_and_Triangle<> center, Editor_Interactive & parent, Editor_Action_Args & args);
+
+	Editor_Action_Args format_args_impl(Editor_Interactive & parent);
+
 	char const * get_sel_impl() const {return "pics/fsel.png";}
-	bool operates_on_triangles() const throw () {return true;};
+	bool operates_on_triangles() const throw() {return true;};
 };
 
 #endif

=== modified file 'src/editor/tools/editor_tool.h'
--- src/editor/tools/editor_tool.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/editor_tool.h	2012-02-14 11:56:48 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2012 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
 #include <boost/noncopyable.hpp>
 
 #include "logic/widelands_geometry.h"
+#include "editor_action_args.h"
 
 struct Editor_Interactive;
 namespace Widelands {struct Map;}
@@ -36,35 +37,58 @@
  * tools).
  */
 struct Editor_Tool : boost::noncopyable {
-	Editor_Tool(Editor_Tool & second, Editor_Tool & third) :
-	m_second(second), m_third(third)
+	Editor_Tool(Editor_Tool & second, Editor_Tool & third, bool uda = true) :
+		m_second(second), m_third(third), undoable(uda)
 	{}
 	virtual ~Editor_Tool() {}
 
 	enum Tool_Index {First, Second, Third};
 	int32_t handle_click
-		(const Tool_Index i,
-		 Widelands::Map & map, Widelands::Node_and_Triangle<> const center,
-		 Editor_Interactive & parent)
-	{
-		return
-			(i == First ? *this : i == Second ? m_second : m_third)
-			.handle_click_impl(map, center, parent);
-	}
+	(const Tool_Index i,
+	 Widelands::Map & map, Widelands::Node_and_Triangle<> const center,
+	 Editor_Interactive & parent, Editor_Action_Args & args) {
+		return
+		    (i == First ? *this : i == Second ? m_second : m_third)
+		    .handle_click_impl(map, center, parent, args);
+	}
+
+	int32_t handle_undo
+	(const Tool_Index i,
+	 Widelands::Map & map, Widelands::Node_and_Triangle<> const center,
+	 Editor_Interactive & parent, Editor_Action_Args & args) {
+		return
+		    (i == First ? *this : i == Second ? m_second : m_third)
+		    .handle_undo_impl(map, center, parent, args);
+	}
+
 	const char * get_sel(const Tool_Index i) {
 		return
-			(i == First ? *this : i == Second ? m_second : m_third)
-			.get_sel_impl();
-	}
-
+		    (i == First ? *this : i == Second ? m_second : m_third)
+		    .get_sel_impl();
+	}
+
+	Editor_Action_Args format_args(const Tool_Index i, Editor_Interactive & parent) {
+		return
+		    (i == First ? *this : i == Second ? m_second : m_third)
+		    .format_args_impl(parent);
+	}
+
+	bool is_unduable() { return undoable; }
+	virtual Editor_Action_Args format_args_impl(Editor_Interactive & parent) {
+		return Editor_Action_Args(parent);
+	}
 	virtual int32_t handle_click_impl
-		(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &)
-		= 0;
+	(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &, Editor_Action_Args &)
+	= 0;
+	virtual int32_t handle_undo_impl
+	(Widelands::Map &, Widelands::Node_and_Triangle<>, Editor_Interactive &, Editor_Action_Args &)
+	{ return 0; } // non unduable tools don't need to implement this.
 	virtual const char * get_sel_impl() const = 0;
 	virtual bool operates_on_triangles() const {return false;};
 
 protected:
 	Editor_Tool & m_second, & m_third;
+	bool undoable;
 };
 
 #endif

=== added file 'src/editor/tools/editor_tool_action.h'
--- src/editor/tools/editor_tool_action.h	1970-01-01 00:00:00 +0000
+++ src/editor/tools/editor_tool_action.h	2012-02-14 11:56:48 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef EDITOR_TOOL_ACTION_H
+#define EDITOR_TOOL_ACTION_H
+
+#include "logic/widelands_geometry.h"
+#include "editor_action_args.h"
+
+struct Editor_Tool;
+namespace Widelands {  class map; }
+struct Editor_Interactive;
+
+
+/// Class to save an action done by an editor tool
+// implementations in editor_history.cc
+struct Editor_Tool_Action {
+	Editor_Tool & tool;
+
+	uint32_t i;
+	Widelands::Map & map;
+	Widelands::Node_and_Triangle<> center;
+	Editor_Interactive & parent;
+
+	Editor_Action_Args * args;
+
+	Editor_Tool_Action
+	(Editor_Tool & t, uint32_t ind,
+	 Widelands::Map & m, Widelands::Node_and_Triangle<> c,
+	 Editor_Interactive & p, Editor_Action_Args nargs):
+		tool(t), i(ind), map(m), center(c), parent(p) {
+		args = new Editor_Action_Args(parent);
+		*args = nargs;
+		args->refcount++;
+	}
+
+	~Editor_Tool_Action() {
+		if (args->refcount <= 1) delete args;
+		else args->refcount--;
+	}
+
+	Editor_Tool_Action(const Editor_Tool_Action & b):
+		tool(b.tool), i(b.i), map(b.map), center(b.center), parent(b.parent), args(b.args)
+	{ args->refcount++; }
+};
+
+#endif
\ No newline at end of file

=== modified file 'src/editor/tools/multi_select.h'
--- src/editor/tools/multi_select.h	2011-11-30 21:38:37 +0000
+++ src/editor/tools/multi_select.h	2012-02-14 11:56:48 +0000
@@ -58,10 +58,10 @@
 	int32_t get_nr_enabled() const {return m_nr_enabled;}
 	int32_t get_random_enabled() const {
 		const int32_t rand_value =
-			static_cast<int32_t>
-				(static_cast<double>(get_nr_enabled())
-				 *
-				 rand() / (RAND_MAX + 1.0));
+		    static_cast<int32_t>
+		    (static_cast<double>(get_nr_enabled())
+		     *
+		     rand() / (RAND_MAX + 1.0));
 		int32_t i = 0;
 		int32_t j = rand_value + 1;
 		while (j) {if (is_enabled(i)) --j; ++i;}


Follow ups