An object can “live” in the following three locations:
When an object is created, a transaction (see Transactions and topological sorting)
is active. Every transaction uses a temp.
Transactions working with graphic objects use the temp
of the
current transaction page, transactions working with non-graphic objects
use the obj_temp
object.
The newly created object is initialized to have the temp as its parent (we say that the object is linked in the temp). Then, inside the transaction, it can be relinked into an object in the universe. If not, it is relinked into the zombie after the end of the transaction. From there, it can be then relinked via the temp into an object in the universe.
The objects in the zombie are deleted automatically when their reference count becomes zero. If an object is relinked, its children are not – their parent pointers remain unchanged. For example, if you unlink a page, it goes to the obj-zombie, but the page's contents stay linked in the page. When you undo the last action, the page is resurrected with its contents as well.
In the picture, you can see an example of object structure of zombie.
There are two zombie objects: one for graphic objects (go
s) and one for
the non-graphic ones (obj
). Every object linked in the zombie points
to its previous parent from where it was unlinked; as observed in the picture,
the previous parent might be in the zombie as well. All the pointing objects
from zombie keep a reference of the parent so that the pointer does not get
invalid.
The zombie and temp objects cannot be accessed directly; instead, there are these functions that do the linking:
obj_link(struct obj* obj, struct obj* father); obj_unlink(struct obj* obj); obj_relink(struct obj *obj, struct obj *father, struct obj *old_father); go_link_after(struct go *go, struct go_group *group, struct go *after); go_unlink(struct go *go); go_relink(struct go *go, struct go_group *group, struct go *after);
and their various special cases for convenience. They use the temp internally.