diff -r -u -X exclude trunk/gtk2_ardour/ardour_ui.cc snapshots/gtk2_ardour/ardour_ui.cc
--- trunk/gtk2_ardour/ardour_ui.cc	2007-03-20 17:42:40.000000000 +0000
+++ snapshots/gtk2_ardour/ardour_ui.cc	2007-03-20 17:43:03.000000000 +0000
@@ -1537,6 +1537,8 @@
 	}
 }
 
+/** Ask the user for the name of a new shapshot and then take it.
+ */
 void
 ARDOUR_UI::snapshot_session ()
 {
diff -r -u -X exclude trunk/gtk2_ardour/editor.cc snapshots/gtk2_ardour/editor.cc
--- trunk/gtk2_ardour/editor.cc	2007-03-20 17:42:40.000000000 +0000
+++ snapshots/gtk2_ardour/editor.cc	2007-03-21 12:10:55.000000000 +0000
@@ -40,6 +40,7 @@
 #include <gtkmm2ext/tearoff.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/window_title.h>
+#include <gtkmm2ext/choice.h>
 
 #include <ardour/audio_track.h>
 #include <ardour/audio_diskstream.h>
@@ -3372,6 +3373,9 @@
 	return false;
 }
 
+
+/** A new snapshot has been selected.
+ */
 void
 Editor::snapshot_display_selection_changed ()
 {
@@ -3396,7 +3400,93 @@
 bool
 Editor::snapshot_display_button_press (GdkEventButton* ev)
 {
-	 return false;
+	if (ev->button == 3) {
+		/* Right-click on the snapshot list. Work out which snapshot it
+		   was over. */
+		Gtk::TreeModel::Path path;
+		Gtk::TreeViewColumn* col;
+		int cx;
+		int cy;
+		snapshot_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, col, cx, cy);
+		Gtk::TreeModel::iterator iter = snapshot_display_model->get_iter (path);
+		if (iter) {
+			Gtk::TreeModel::Row row = *iter;
+			popup_snapshot_context_menu (ev->button, ev->time, row[snapshot_display_columns.real_name]);
+		}
+		return true;
+	}
+
+	return false;
+}
+
+
+/** Pop up the snapshot display context menu.
+ * @param button Button used to open the menu.
+ * @param time Menu open time.
+ * @snapshot_name Name of the snapshot that the menu click was over.
+ */
+
+void
+Editor::popup_snapshot_context_menu (int button, int32_t time, Glib::ustring snapshot_name)
+{
+	using namespace Menu_Helpers;
+
+	MenuList& items (snapshot_context_menu.items());
+	items.clear ();
+
+	const bool modification_allowed = (session->snap_name() != snapshot_name && session->name() != snapshot_name);
+
+	items.push_back (MenuElem (_("Remove"), bind (mem_fun (*this, &Editor::remove_snapshot), snapshot_name)));
+	if (!modification_allowed) {
+		items.back().set_sensitive (false);
+	}
+
+	items.push_back (MenuElem (_("Rename"), bind (mem_fun (*this, &Editor::rename_snapshot), snapshot_name)));
+	if (!modification_allowed) {
+		items.back().set_sensitive (false);
+	}
+
+	snapshot_context_menu.popup (button, time);
+}
+
+void
+Editor::rename_snapshot (Glib::ustring old_name)
+{
+	ArdourPrompter prompter(true);
+
+	string new_name;
+
+	prompter.set_name ("Prompter");
+	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
+	prompter.set_prompt (_("New name of snapshot"));
+	prompter.set_initial_text (old_name);
+	
+	if (prompter.run() == RESPONSE_ACCEPT) {
+		prompter.get_result (new_name);
+		if (new_name.length()) {
+			session->rename_state (old_name, new_name);
+		        redisplay_snapshots ();
+		}
+	}
+}
+
+
+void
+Editor::remove_snapshot (Glib::ustring name)
+{
+	vector<string> choices;
+
+	std::string prompt  = string_compose (_("Do you really want to remove snapshot \"%1\" ?\n(cannot be undone)"), name);
+
+	choices.push_back (_("No, do nothing."));
+	choices.push_back (_("Yes, remove it."));
+
+	Gtkmm2ext::Choice prompter (prompt, choices);
+
+	if (prompter.run () == 1) {
+		session->remove_state (name);
+		redisplay_snapshots ();
+	}
 }
 
 void
diff -r -u -X exclude trunk/gtk2_ardour/editor.h snapshots/gtk2_ardour/editor.h
--- trunk/gtk2_ardour/editor.h	2007-03-19 16:49:29.000000000 +0000
+++ snapshots/gtk2_ardour/editor.h	2007-03-21 12:10:55.000000000 +0000
@@ -770,10 +770,12 @@
 	SnapshotDisplayModelColumns snapshot_display_columns;
 	Glib::RefPtr<Gtk::ListStore> snapshot_display_model;
 	Gtk::TreeView snapshot_display;
+	Gtk::Menu snapshot_context_menu;
 
 	bool snapshot_display_button_press (GdkEventButton*);
 	void snapshot_display_selection_changed ();
 	void redisplay_snapshots();
+	void popup_snapshot_context_menu (int, int32_t, Glib::ustring);
 
 	/* named selections */
 
@@ -795,6 +797,8 @@
 	void create_named_selection ();
 	void paste_named_selection (float times);
 	void remove_selected_named_selections ();
+	void remove_snapshot (Glib::ustring);
+	void rename_snapshot (Glib::ustring);
 
 	void handle_new_named_selection ();
 	void add_named_selection_to_named_selection_display (ARDOUR::NamedSelection&);
diff -r -u -X exclude trunk/libs/ardour/ardour/session.h snapshots/libs/ardour/ardour/session.h
--- trunk/libs/ardour/ardour/session.h	2007-03-20 08:38:53.000000000 +0000
+++ snapshots/libs/ardour/ardour/session.h	2007-03-21 12:12:40.000000000 +0000
@@ -411,6 +411,8 @@
 	int save_template (string template_name);
         int save_history (string snapshot_name = "");
         int restore_history (string snapshot_name);
+	void remove_state (string snapshot_name);
+	void rename_state (string old_name, string new_name);
 
 	static int rename_template (string old_name, string new_name);
 
diff -r -u -X exclude trunk/libs/ardour/session_state.cc snapshots/libs/ardour/session_state.cc
--- trunk/libs/ardour/session_state.cc	2007-03-20 08:38:53.000000000 +0000
+++ snapshots/libs/ardour/session_state.cc	2007-03-21 14:15:34.000000000 +0000
@@ -593,6 +593,48 @@
 	unlink (xml_path.c_str());
 }
 
+/** Rename a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::rename_state (string old_name, string new_name)
+{
+	if (old_name == _current_snapshot_name || old_name == _name) {
+		/* refuse to rename the current snapshot or the "main" one */
+		return;
+	}
+	
+	const string old_xml_path = _path + old_name + _statefile_suffix;
+	const string new_xml_path = _path + new_name + _statefile_suffix;
+
+	if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
+		error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
+	}
+}
+
+/** Remove a state file.
+ * @param snapshot_name Snapshot name.
+ */
+void
+Session::remove_state (string snapshot_name)
+{
+	if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
+		/* refuse to remove the current snapshot or the "main" one */
+		return;
+	}
+	
+	const string xml_path = _path + snapshot_name + _statefile_suffix;
+
+	/* make a backup copy of the state file */
+	const string bak_path = xml_path + ".bak";
+	if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
+		copy_file (xml_path, bak_path);
+	}
+
+	/* and delete it */
+	unlink (xml_path.c_str());
+}
+
 int
 Session::save_state (string snapshot_name, bool pending)
 {
@@ -618,10 +660,12 @@
 
 	if (!pending) {
 
+		/* proper save: use _statefile_suffix (.ardour in English) */
 		xml_path = _path;
 		xml_path += snapshot_name;
 		xml_path += _statefile_suffix;
 
+		/* make a backup copy of the old file */
 		bak_path = xml_path;
 		bak_path += ".bak";
 		
@@ -631,6 +675,7 @@
 
 	} else {
 
+		/* pending save: use _pending_suffix (.pending in English) */
 		xml_path = _path;
 		xml_path += snapshot_name;
 		xml_path += _pending_suffix;
