Programming for undo/redo ~~~~~~~~~~~~~~~~~~~~~~~~~ The following document provides an overview on libuundo best practices. Assume an application that has N different user actions. These are each a single operation manipulating the global state (e.g. a design in a CAD program). The application shall set up an uundo_list_t for the design. It needs to be initialized before the first use, using uundo_list_init(). The application should define N different atomic operators of type uundo_oper_t, one for each operation. Each atomic operation should be implemented as 5 functions: I. The REDO function should: execute whatever manipulations on the global state, using udata; this is where the actual job is done. II. the UNDO function should: execute the reverse of what the REDO function did, using the udata prepared by the DO function III. the FREE function should: destroy fields of the udata IV. the PRINT function should: render the fields of udata in a human readable form V. The PERFORM function should: 1. call uundo_freeze_serial() 2. call uundo_append() to get a large enough storage, called udata, for saving the details of the operation 3. perform the action by calling the REDO function with udata 4. call uundo_unfreeze_serial() 5. call uundo_inc_serial() The oper struct shall be set up so that: .item_free = the FREE function .item_undo = the UNDO function .item_redo = the REDO function .item_print = the PRINT function Upon user input, the application should call the PERFORM function, which would add the user action to the undo list and perform it using the same REDO function that would be used on a redo request. Note that UNDO and REDO both work from the same udata and one is the inverse transformation of the other. The udata is prepared only once, in PERFORM and is free'd in FREE when the item is removed from the undo list. Once the above infrastructure is set up, upon user undo and redo the application should call uundo_undo() and uundo_redo(). If the design is unloaded or the application exits, uundo_list_uninit() should be called to reclaim memory allocated for the undo list.