copied from sourceforge. some whitespace & casing changes