If you are on a 32 bit platform...
Sample button status every 20 ms and perform this: history = (history<<1) | ((bool)button & 1)
Then you can check the amount of cleared bits (buttons always go low when pressed) and detect short press (0xFFFFFFF0), long press (0x00000000), medium press (0xFFFF0000), double press (0xFF00FF00) you name it.
All in the software, I've only used long and short press, double and medium are a lot more effort to program.
But now I have a flawless relay control button with mode select when you hold it.
Tip, use the setbits instruction to prevent useless comparisons... If you target has such instruction.