initial version submitted by gavin and slightly cleaned up