Index: src/Actions/WorldAction/CenterOnEdgeAction.cpp
===================================================================
--- src/Actions/WorldAction/CenterOnEdgeAction.cpp	(revision 23526ca91bfbf2679afc5840c9ee7c434447dce7)
+++ src/Actions/WorldAction/CenterOnEdgeAction.cpp	(revision de7d1dba7824fa30f6db19bd9e5951529efb0758)
@@ -18,14 +18,22 @@
 #endif
 
+// include headers that implement a archive in simple text format
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+#include "boost/serialization/vector.hpp"
+
 #include "CodePatterns/MemDebug.hpp"
 
 #include "atom.hpp"
 #include "CodePatterns/Log.hpp"
+#include "LinearAlgebra/MatrixContent.hpp"
+#include "LinearAlgebra/RealSpaceMatrix.hpp"
 #include "LinearAlgebra/Vector.hpp"
+#include "molecule.hpp"
 #include "World.hpp"
-#include "LinearAlgebra/RealSpaceMatrix.hpp"
 
 #include <iostream>
 #include <string>
+#include <vector>
 
 #include "Actions/WorldAction/CenterOnEdgeAction.hpp"
@@ -44,8 +52,21 @@
   getParametersfromValueStorage();
 
+  // create undo state
+  std::stringstream undostream;
+  boost::archive::text_oarchive oa(undostream);
+  const RealSpaceMatrix &matrix = World::getInstance().getDomain().getM();
+  oa << matrix;
+  std::vector< boost::shared_ptr<Vector> > OldPositions;
+  std::vector<atom *> AllAtoms = World::getInstance().getAllAtoms();
+  for (std::vector<atom *>::iterator AtomRunner = AllAtoms.begin(); AtomRunner != AllAtoms.end(); ++AtomRunner)
+    OldPositions.push_back(
+        boost::shared_ptr<Vector>(new Vector(
+            (*AtomRunner)->getPosition()
+            ))
+        );
+
   // get maximum and minimum
-  vector<atom *> AllAtoms = World::getInstance().getAllAtoms();
   ASSERT(AllAtoms.size() > 0, "For CenteronEdge atoms must be present.");
-  vector<atom *>::iterator AtomRunner = AllAtoms.begin();
+  std::vector<atom *>::iterator AtomRunner = AllAtoms.begin();
   Min = (*AtomRunner)->getPosition();
   Max = (*AtomRunner)->getPosition();
@@ -67,5 +88,5 @@
   World::getInstance().setDomain(domain);
   // translate all atoms, such that Min is aty (0,0,0)
-  for (vector<atom*>::iterator AtomRunner = AllAtoms.begin(); AtomRunner != AllAtoms.end(); ++AtomRunner)
+  for (std::vector<atom*>::iterator AtomRunner = AllAtoms.begin(); AtomRunner != AllAtoms.end(); ++AtomRunner)
     *(*AtomRunner) -= Min;
 
@@ -73,27 +94,69 @@
   LOG(0, "Box domain is now " << World::getInstance().getDomain().getM());
 
-  return Action::success;
+  // create undo state
+  WorldCenterOnEdgeState *UndoState =
+      new WorldCenterOnEdgeState(
+          undostream.str(),
+          Min,
+          Max,
+          params
+          );
+
+  return Action::state_ptr(UndoState);
 }
 
 Action::state_ptr WorldCenterOnEdgeAction::performUndo(Action::state_ptr _state) {
-//  ParserLoadXyzState *state = assert_cast<ParserLoadXyzState*>(_state.get());
+  WorldCenterOnEdgeState *state = assert_cast<WorldCenterOnEdgeState*>(_state.get());
 
-  return Action::failure;
-//  string newName = state->mol->getName();
-//  state->mol->setName(state->lastName);
-//
-//  return Action::state_ptr(new ParserLoadXyzState(state->mol,newName));
+  // restore domain
+  RealSpaceMatrix matrix;
+  std::stringstream undostream(state->undostring);
+  boost::archive::text_iarchive ia(undostream);
+  ia >> matrix;
+  World::getInstance().setDomain(matrix);
+
+  // translate all atoms back
+  std::vector<atom *> AllAtoms = World::getInstance().getAllAtoms();
+  for (vector<atom*>::iterator AtomRunner = AllAtoms.begin();
+      AtomRunner != AllAtoms.end();
+      ++AtomRunner)
+    *(*AtomRunner) += state->Min;
+
+  // give final box size
+  LOG(0, "Box domain restored to " << World::getInstance().getDomain().getM());
+
+  return Action::state_ptr(_state);
 }
 
 Action::state_ptr WorldCenterOnEdgeAction::performRedo(Action::state_ptr _state){
-  return Action::failure;
+  WorldCenterOnEdgeState *state = assert_cast<WorldCenterOnEdgeState*>(_state.get());
+
+  // set new box size
+  RealSpaceMatrix rmatrix;
+  for (int i=0;i<NDIM;i++) {
+    double tmp = state->Max[i]-state->Min[i];
+    tmp = fabs(tmp)>=1. ? tmp : 1.0;
+    rmatrix.at(i,i) = tmp;
+  }
+  World::getInstance().setDomain(rmatrix);
+  // translate all atoms, such that Min is aty (0,0,0)
+  std::vector<atom *> AllAtoms = World::getInstance().getAllAtoms();
+  for (vector<atom*>::iterator AtomRunner = AllAtoms.begin();
+      AtomRunner != AllAtoms.end();
+      ++AtomRunner)
+    *(*AtomRunner) -= state->Min;
+
+  // give final box size
+  LOG(0, "Box domain is again " << World::getInstance().getDomain().getM());
+
+  return Action::state_ptr(_state);
 }
 
 bool WorldCenterOnEdgeAction::canUndo() {
-  return false;
+  return true;
 }
 
 bool WorldCenterOnEdgeAction::shouldUndo() {
-  return false;
+  return true;
 }
 /** =========== end of function ====================== */
Index: src/Actions/WorldAction/CenterOnEdgeAction.def
===================================================================
--- src/Actions/WorldAction/CenterOnEdgeAction.def	(revision 23526ca91bfbf2679afc5840c9ee7c434447dce7)
+++ src/Actions/WorldAction/CenterOnEdgeAction.def	(revision de7d1dba7824fa30f6db19bd9e5951529efb0758)
@@ -7,5 +7,5 @@
 
 // all includes and forward declarations necessary for non-integral types below
-
+#include "LinearAlgebra/Vector.hpp"
 
 // i.e. there is an integer with variable name Z that can be found in
@@ -18,6 +18,6 @@
 #undef paramreferences
 
-#undef statetypes
-#undef statereferences
+#define statetypes (std::string)(Vector)(Vector)
+#define statereferences (undostring)(Min)(Max)
 
 // some defines for all the names, you may use ACTION, STATE and PARAMS
Index: tests/regression/Domain/CenterOnEdge/post/test-undo.conf
===================================================================
--- tests/regression/Domain/CenterOnEdge/post/test-undo.conf	(revision de7d1dba7824fa30f6db19bd9e5951529efb0758)
+++ tests/regression/Domain/CenterOnEdge/post/test-undo.conf	(revision de7d1dba7824fa30f6db19bd9e5951529efb0758)
@@ -0,0 +1,73 @@
+# ParallelCarParinello - main configuration file - created with molecuilder
+
+mainname	pcp	# programm name (for runtime files)
+defaultpath	not specified	# where to put files during runtime
+pseudopotpath	not specified	# where to find pseudopotentials
+
+ProcPEGamma	8	# for parallel computing: share constants
+ProcPEPsi	1	# for parallel computing: share wave functions
+DoOutVis	0	# Output data for OpenDX
+DoOutMes	1	# Output data for measurements
+DoOutOrbitals	0	# Output all Orbitals
+DoOutCurr	0	# Ouput current density for OpenDx
+DoOutNICS	0	# Output Nucleus independent current shieldings
+DoPerturbation	0	# Do perturbation calculate and determine susceptibility and shielding
+DoFullCurrent	0	# Do full perturbation
+DoConstrainedMD	0	# Do perform a constrained (>0, relating to current MD step) instead of unconstrained (0) MD
+Thermostat	Berendsen	2.5	# Which Thermostat and its parameters to use in MD case.
+CommonWannier	0	# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center
+SawtoothStart	0.01	# Absolute value for smooth transition at cell border 
+VectorPlane	0	# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot
+VectorCut	0	# Cut plane axis value
+AddGramSch	1	# Additional GramSchmidtOrtogonalization to be safe
+Seed		1	# initial value for random seed for Psi coefficients
+
+MaxOuterStep	0	# number of MolecularDynamics/Structure optimization steps
+Deltat	0.01	# time per MD step
+OutVisStep	10	# Output visual data every ...th step
+OutSrcStep	5	# Output "restart" data every ..th step
+TargetTemp	0.000950045	# Target temperature
+MaxPsiStep	3	# number of Minimisation steps per state (0 - default)
+EpsWannier	1e-07	# tolerance value for spread minimisation of orbitals
+
+# Values specifying when to stop
+MaxMinStep	100	# Maximum number of steps
+RelEpsTotalE	1e-07	# relative change in total energy
+RelEpsKineticE	1e-05	# relative change in kinetic energy
+MaxMinStopStep	1	# check every ..th steps
+MaxMinGapStopStep	1	# check every ..th steps
+
+# Values specifying when to stop for INIT, otherwise same as above
+MaxInitMinStep	100	# Maximum number of steps
+InitRelEpsTotalE	1e-05	# relative change in total energy
+InitRelEpsKineticE	0.0001	# relative change in kinetic energy
+InitMaxMinStopStep	1	# check every ..th steps
+InitMaxMinGapStopStep	1	# check every ..th steps
+
+BoxLength			# (Length of a unit cell)
+20	
+0	20	
+0	0	20	
+
+ECut		128	# energy cutoff for discretization in Hartrees
+MaxLevel	5	# number of different levels in the code, >=2
+Level0Factor	2	# factor by which node number increases from S to 0 level
+RiemannTensor	0	# (Use metric)
+PsiType		0	# 0 - doubly occupied, 1 - SpinUp,SpinDown
+MaxPsiDouble	1	# here: specifying both maximum number of SpinUp- and -Down-states
+PsiMaxNoUp	1	# here: specifying maximum number of SpinUp-states
+PsiMaxNoDown	1	# here: specifying maximum number of SpinDown-states
+AddPsis		0	# Additional unoccupied Psis for bandgap determination
+
+RCut		20	# R-cut for the ewald summation
+StructOpt	0	# Do structure optimization beforehand
+IsAngstroem	1	# 0 - Bohr, 1 - Angstroem
+RelativeCoord	0	# whether ion coordinates are relative (1) or absolute (0)
+MaxTypes	1	# maximum number of different ion types
+
+# Ion type data (PP = PseudoPotential, Z = atomic number)
+#Ion_TypeNr.	Amount	Z	RGauss	L_Max(PP)L_Loc(PP)IonMass	# chemical name, symbol
+Ion_Type1	2	1	1.0	3	3	1.00800000000	Hydrogen	H
+#Ion_TypeNr._Nr.R[0]    R[1]    R[2]    MoveType (0 MoveIon, 1 FixedIon)
+Ion_Type1_1	10.000000000	10.000000000	10.000000000	0 # molecule nr 0
+Ion_Type1_2	11.000000000	10.000000000	12.000000000	0 # molecule nr 1
Index: tests/regression/Domain/CenterOnEdge/testsuite-domain-center-on-edge.at
===================================================================
--- tests/regression/Domain/CenterOnEdge/testsuite-domain-center-on-edge.at	(revision 23526ca91bfbf2679afc5840c9ee7c434447dce7)
+++ tests/regression/Domain/CenterOnEdge/testsuite-domain-center-on-edge.at	(revision de7d1dba7824fa30f6db19bd9e5951529efb0758)
@@ -7,5 +7,5 @@
 AT_CHECK([/bin/cp -f ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/pre/test.conf $file], 0)
 AT_CHECK([chmod u+w $file], 0)
-AT_CHECK([../../molecuilder -i $file  -O], 0, [stdout], [stderr])
+AT_CHECK([../../molecuilder -i $file -O], 0, [stdout], [stderr])
 AT_CHECK([fgrep "Box domain is now" stdout], 0, [ignore], [ignore])
 AT_CHECK([diff $file ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/post/test.conf], 0, [stdout], [stderr])
@@ -15,5 +15,4 @@
 
 AT_SETUP([Domain - set domain to minimum size with Undo])
-AT_XFAIL_IF([/bin/true])
 AT_KEYWORDS([domain center-edge undo])
 
@@ -21,7 +20,7 @@
 AT_CHECK([/bin/cp -f ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/pre/test.conf $file], 0)
 AT_CHECK([chmod u+w $file], 0)
-AT_CHECK([../../molecuilder -i $file  -O --undo], 0, [stdout], [stderr])
+AT_CHECK([../../molecuilder -i $file -O --undo], 0, [stdout], [stderr])
 AT_CHECK([fgrep "Box domain is now" stdout], 0, [ignore], [ignore])
-AT_CHECK([diff $file ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/post/test.conf], 0, [stdout], [stderr])
+AT_CHECK([diff $file ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/post/test-undo.conf], 0, [stdout], [stderr])
 
 AT_CLEANUP
@@ -29,5 +28,4 @@
 
 AT_SETUP([Domain - set domain to minimum size with Redo])
-AT_XFAIL_IF([/bin/true])
 AT_KEYWORDS([domain center-edge redo])
 
@@ -35,5 +33,5 @@
 AT_CHECK([/bin/cp -f ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/pre/test.conf $file], 0)
 AT_CHECK([chmod u+w $file], 0)
-AT_CHECK([../../molecuilder -i $file  -O --undo --redo], 0, [stdout], [stderr])
+AT_CHECK([../../molecuilder -i $file -O --undo --redo], 0, [stdout], [stderr])
 AT_CHECK([fgrep "Box domain is now" stdout], 0, [ignore], [ignore])
 AT_CHECK([diff $file ${abs_top_srcdir}/tests/regression/Domain/CenterOnEdge/post/test.conf], 0, [stdout], [stderr])
