The easiest way is to capture any change to any of included control and write down the state (contents, selection, caret position) of all 4 controls together. Do this for every change and you have an undo stack. Now when you need to undo the operation, you restore all controls to their saved state.
This scheme can be quite resource-consuming and once implemented you would want to optimize it by saving only the difference or the last operation done on particular control. The problems are
(a) standard edit / memo won't give you information on what exactly has changed, so you would need to somehow calculate the change (eg. by comparing it with previously recorded state, but this means that you'll need to "rebuild" contents from the initial state and through all the changes, then compare current-1 state with current state just to find out the change,
(b) standard controls handle undo operation themselves and the user can revert one control thus breaking the order of your undo stack.
Maybe you can use some third-party edit / memo control that would be more tolerant to your needs and will let you control undo/redo operations. For example, I once created TElEdit control for ElPack (now LMD ElPack owned by LMD Innovative) and that control among other features had undo/redo stack and I know how TElEdit could assist you with slight modifications of its source code. You might want to check TElEdit or other similar component to see what they can offer you.