In order to make a widget binary compatible with future releases of XmPrimitive and XmManager that have expanded their instance records, you must do the following:
By doing all these steps, a widget written and compiled at the current release of Motif should continue to work without recoding or recompiling at future releases. If you do not do these steps when writing a widget, it is probable that your widgets will have to be recompiled for future releases.
The only Exm widget that is binary compatible with future releases is the ExmTabButton widget.
The index macro represents your widget's place in the hierarchy. The index macro is defined in the widget private header file. Use the following syntax to define the index macro:
#define YourWidgetNameIndex (SuperclassIndexMacro + 1)
For example, XmPrimitive is the superclass of ExmSimple. The SuperclassIndexMacro associated with XmPrimitive is called XmPrimitiveIndex. Therefore, the index macro of ExmSimple is defined as follows:
#define ExmSimpleIndex (XmPrimitiveIndex + 1)
Similarly, the index macro of ExmString is defined as follows:
#define ExmStringIndex (ExmSimpleIndex + 1)
Note that, although ExmTabButton is the only binary-compatible Exm widget, all the widgets that precede it in the widget hierarchy must define index macros.
To ensure binary compatibility, your widget source code file must define an XmField access macro for each field that your source code file accesses. In this context, a "field" means a member of a widget instance record in any subclass of XmPrimitive and XmManager. For example, ExmTabButton access the following three members of widget instance records of subclasses of XmPrimitive:
Therefore, the source code file of ExmTabButton contains the following 5 macro definitions:
#define OpenSide(w) XmField(w, offsets, ExmTabButton, open_side, XtEnum) #define JoinShadowThickness(w) XmField(w, offsets, ExmTabButton, join_shadow_thickness, Dimension) #define VisualArmed(w) XmField(w, offsets, ExmCommandButton, visual_armed, Boolean) #define SimpleShape(w) XmField(w, offsets, ExmSimple, simple_shape, unsigned char) #define NeedToReconfigure(w) XmField(w, offsets, ExmSimple, need_to_reconfigure, Boolean)
To ensure binary compatibility, you must define the resources array as an array of XmPartResource instead of an array of XtResource. In addition, the fifth field of each resource record should access offsets through the XmPartOffset macro instead of the XtOffsetOf macro.
For example, following is the resources array of ExmTabButton:
static XmPartResource resources[] = { { ExmNopenSide, ExmCOpenSide, ExmROpenSide, sizeof (XtEnum), XmPartOffset (ExmTabButton, open_side), XmRImmediate, (XtPointer) XmLEFT }, };
To ensure binary compatibility, you must set the version field of the CoreClassPart to XtVersionDontCheck instead of XtVersion. For example, the CoreClassPart of ExmTabButton contains the following version field:
/* version */ XtVersionDontCheck,
For binary compatibility, a widget must declare an XmOffsetPtr variable. By convention, the XmOffsetPtr is declared immediately following the declaration of trait record variables in the widget source code file.
For example, following is the declaration of the XmOffsetPtr variable that appears in ExmTabButton:
/* Part Offset table for XmResolvePartOffsets */ static XmOffsetPtr offsets;
Your widget must call XmeResolvePartOffsets prior to the first time that an XmField macro (defined in Step 2) is used in a widget method. In other words, in order for an XmField macro to work properly, XmeResolvePartOffsets must already have been called.
For example, following is the call to XmeResolvePartOffsets that appears in the ClassInitialize method of ExmTabButton:
XmeResolvePartOffsets(exmTabButtonWidgetClass, &offsets, NULL);
Instead of using any fields from widget instance parts directly, you must access them through the XmField access macros you created back in Step 2.
For example, the Initialize method of ExmStringTransfer accesses the draw_bevel field as follows:
DrawBevel(new) = False; /* right */
rather than as follows:
nw->tab_button.draw_bevel = False; /* wrong */
The latter way of accessing draw_bevel is adequate for creating a working widget but does not create a binary-compatible widget.