There are really five important classes in M*TIF: ExtObject, Gadget, Primitive, Manager and VendorShell. Nearly every Motif widget class inherits behavior from one of these. Some (XmDialogShell for example) inherit from more than one. While this may seem a statement of the obvious, it must be pointed out that the easiest way for a class to inherit behavior from a superclass is to subclass from the appropriate ``Core'' widget. Those aforementioned classes are the ``Core'' M*TIF classes (for objects, window-less widgets, core, constraint, and shell widgets respectively). Thus, if we provide the M*TIF ``Core'' widgets the ability to handle synthetic resources, all subclasses will inherit that behavior. In practice, the VendorShell class behavior is dictated by the X specification. Any special behavior related to the VendorShell must be specified in the VendorShell extension object, which is subclassed from ExtObj - thus the true core widget set contains only four classes.
There are only four class methods that deal with resource manipulation. They are the initialize() method, the set_values() method, the Constraint set_values() method, and the get_values_hook() method. Really there are two more, the set_values_almost() method, and the set_values_hook() method; the latter is obsolete, the former is in practice never used.
In terms of resource manipulation, the Core set_values() method and the Constraint set_values() method can be combined, by simply checking to see if the parent is a Constraint (read Manager) subclass. The only difference is where the resources are defined (self or parent). Second, the alterations that the initialize() method and the set_values() method perform based on the argument lists are identical; so we can use the same function for both. Therefore, we really have only two cases to handle - the case where the user specifies the value for a resource (initialize() and set_values()), and the case where the user wants to find the value of a resource (get_values_hook()).
Thus, there are two major sets of functions that implement the synthetic resource behavior: four import functions with the postfix *ImportArgs(), and five export functions ending with *GetValuesHook(). Both sets appear in ResInd.c. The prototypes are as follows:
_XmExtImportArgs_XmPrimitiveImportArgs_XmGadgetImportArgs_XmGadgetImportSecondaryArgs_XmManagerImportArgs_XmPrimitiveGetValuesHook_XmGadgetGetValuesHook_XmManagerGetValuesHook_XmExtGetValuesHook
void _XmExtImportArgs(Widget w, ArgList args, Cardinal *num_args); void _XmPrimitiveImportArgs(Widget w, ArgList args, Cardinal *num_args); void _XmGadgetImportArgs(Widget w, ArgList args, Cardinal *num_args); void _XmGadgetImportSecondaryArgs(Widget w, ArgList args, Cardinal *num_args); void _XmManagerImportArgs(Widget w, ArgList args, Cardinal *num_args); void _XmPrimitiveGetValuesHook(Widget w, ArgList args, Cardinal *num_args); void _XmGadgetGetValuesHook(Widget w, ArgList args, Cardinal *num_args); void _XmManagerGetValuesHook(Widget w, ArgList args, Cardinal *num_args); void _XmExtGetValuesHook(Widget w, ArgList args, Cardinal *num_args);
The import functions are called from the initialize() and set_values() methods in the relevant widget classes directly. The export functions are directly registered in the core get_values_hook() method.
Note that there is an extra function _XmGadgetImportSecondaryArgs() unique to Gadgets. It is a result of the ``cache'' subparts that nearly all Gadgets have. It provides the mechanism to import and export resources from the subpart.
The implementation of the functions is fairly ugly, and I wouldn't mind suggestions on how to improve their efficiency. Essentially, they use a doubly nested loop, going through the resource request list, and finding matches in the synthetic resource list. If a match is found, the import or export procedure in the synthetic resource structure is invoked.
I'll not go into further detail about how the M*TIF ``core'' widget classes hook into the synthetic resource mechanism. If you read the code to Gadget, Primitive, or Manager, it is fairly obvious (for example, just a call to _XmPrimitiveImportArgs() in Primitive's set_values_method).
One fairly important thing to note, is that the ``core'' class_part_initialize() methods combine a subclass's synthetic resources with all of the superclass's synthetic resources. This is done via _XmBuildResources()_XmBuildResources. This way, access to inherited synthetic resources get sped up because M*TIF doesn't need to search for them in the superclasses. If you subclass from a widget that has synthetic resources, but add no new ones, you'll end up with synthetic resources after the class_part_init() method has been called.