On most systems, Builder Xcessory accesses widgets by loading a shared library when the widget class is first accessed. To load widgets dynamically using Builder Xcessory, the following two requirements must be met:
-
Widgets must be compiled into a shared library.
On most systems, you can do this by compiling the various objects of the library with the position-independent code flag and linking the library with any other libraries on which the new library depends. Consult your system and compiler manuals for exact details on building shared libraries.
-
Widgets must have a Motif-style creation function that returns an unmanaged instance of the widget.
A Motif-style creation function has the following function prototype:
-
Widget CreateFunction(Widget parent, char *name,
ArgList args, Cardinal num_args)
-
Widget CreateFunction(Widget parent, char *name,
How Builder Xcessory Searches for a Library
The first time you create an instance of a widget in a shared library, Builder Xcessory searches for the library in several locations in addition to the usual shared library search path. Once it finds the library, Builder Xcessory loads the library and finds and calls the widget's creation function.
Complete search path
The complete search path is as follows
The name of the shared library to load is specified in the WML file for the widget. Each widget specifies a shared library to find and load in the LoadLibrary WML attribute. For more information on the WML file format, see"Generating WML And Other Control Files" and Chapter 8--Modifying the WML File.
Specifying the Widget Creation Function
On most systems, Builder Xcessory dynamically loads a shared library containing the widget and searches the WML file for the function to use to create it. Set the CreationFunction attribute to name the function to call to create the widget. The function has the same signature as the Xm-style convenience functions described in the section "Creation function". In addition, set the ConvenienceFunction attribute to name the function that the code generator should use in generated code (in most cases, these two functions will have the same value1).
Creation function
The creation function is required for dynamically-loaded widgets. Most widgets written for use with the Motif widget set provide such a function, in the Motif style. For example, ICS EnhancementPak widgets have routines with names such as XiCreateButtonBox.
If the widget you are integrating does not provide such a function, you can easily create one, as shown in the following example:
Compiling the creation function
To compile the creation function, use the following procedure:
- Use the correct position-independent code flag for your compiler.
- Create a shared library that contains this new object and is linked to the necessary widget library.
- Put this new intermediary library in one of the directories that Builder Xcessory searches.
- Specify the new function in the widget's creation function WML attribute.
Adding Widgets Using the bx.o File
On systems running SunOS 4 (or on systems where using shared libraries is not feasible), the widget must be linked into the Builder Xcessory binary, along with a control function that makes a call to extend Builder Xcessory. When you extend Builder Xcessory, you must provide the following three functions, which Builder Xcessory calls at start-up:
In our example, these functions are in a file called addWidget.c
. To create a new version of Builder Xcessory that contains your new widgets, relink addWidget.o
with the object file bx.o
and the libraries containing the widgets to be integrated.
AddUserWidgets is an entry point for Builder Xcessory to use to add new widgets. It takes no arguments and has no return value. If you rebuild Builder Xcessory for any reason, you must provide at least an empty version of AddUserWidgets.
Using AddUserWidgets
Tell Builder Xcessory about the availability of new widgets by making calls to RegisterWidgetExtended from the function AddUserWidgets. Call RegisterWidgetExtended once for each new widget you add to Builder Xcessory. RegisterWidgetExtended has the following function prototype:
- void
-
RegisterWidgetExtended(char *class_name,
WidgetClassRec *class_ptr,
char *conv_fct_name,
XtPointer conv_fct_ptr,
char *include_file,
char *resource_prefix)
class_name Name of widget class being added to Builder Xcessory. For example xmDumbLabelWidgetClass or xiButtonBoxWidgetClass.
class_ptr
Address of the class pointer. For example, the class of XmDumbLabel is xmDumbLabelWidgetClass. Entered as &xmDumbLabelWidgetClass. If NULL, you must provide a convenience function to create the widget.
conv_fct_name
Name of convenience function to create widget. The value should be set to NULL, if there is no special convenience function to create the widget. If this value is NULL, Builder Xcessory uses XtCreateWidget to create an instance of the widget when it generates code.
conv_fct_ptr
Pointer to function named by conv_fct_name. Depending on whether or not class_ptr is NULL, the convenience function should be Motif-style or Xt-style (see "Xt-style creation routine" ). If you provide a function here, Builder Xcessory uses it to create the widget internally.
include_file
File that must be included in order to reference the class_ptr and any other functions or data defined by the widget. For example, XmDumbLabel requires you to include "<Xm/XmDumbLabel.h>".2 If the widget requires more than one include file, separate each file in the string by a space, such as "<Xm/Foo.h> <Xi/Bar.h>". In the unlikely event that the widget does not require an include file, include_file can be NULL.
resource_prefix
Widget set prefix used by the widget for its resource names. For example, Motif uses "Xm" as its resource prefix. The Athena widget set uses "Xt". If you specify NULL for this value, "Xm" is assumed.
Note: When adding multiple widgets, the RegisterWidgetExtended calls must be made in SuperClass to SubClass order. For example, if
you had a widget XmDumbPushButton that was sub-classed from widget XmDumbLabel, you would first call RegisterWidgetExtended for XmDumbLabel and then call RegisterWidgetExtended for XmDumbPushButton.
Example
As an example of using RegisterWidgetExtended, we show the call used to add the XmDumbLabel widget to Builder Xcessory.
The RegisterWidgetExtended call in the AddUserWidgets function allows you to override how widgets are created.
Motif-style creation routine
Builder Xcessory supports two types of creation function. The Motif-style creation routine has the same function prototype as any Motif XmCreate function:
-
Widget CreateFunction(Widget parent, char *name,
ArgList args, Cardinal num_args)
Xt-style creation routine
The Xt-style creation routine has the same function prototype as the XtCreateWidget function:
-
Widget CreateFunction(char *name, WidgetClass widget_class,
Widget parent, ArgList args, Cardinal num_args)
When you register an alternate creation routine, you can choose between either of the two styles. Also, you can choose whether the routine is used internally by Builder Xcessory and/or externally in the code generated by Builder Xcessory.
Using an Xt-style creation routine
To use an Xt-style creation routine, you must provide a value for class_ptr in RegisterWidgetExtended. How you specify values for conv_fct_name and conv_fct_ptr determines where the new creation routine is used.
If you set conv_fct_name to NULL, Builder Xcessory uses XtCreateWidget to create the widget in the code that is generated. If conv_fct_name is not set to NULL, Builder Xcessory uses the string you specified as the name of the function to call to create an instance of the widget.
If you set conv_fct_ptr to NULL, Builder Xcessory uses XtCreateWidget to create the widget internally. If conv_fct_ptr is not set to NULL, Builder Xcessory uses the function you specified to create an instance of the widget.
Using a Motif-style creation routine
If you set class_ptr to NULL in RegisterWidgetExtended, Builder Xcessory assumes a Motif-style creation routine. You must then provide a value for conv_fct_ptr. Otherwise, Builder Xcessory cannot create an instance of the widget.
If you set conv_fct_name to NULL, Builder Xcessory uses XtCreateWidget in the generated code and the function you supplied in conv_fct_ptr for creating widget instances internally.
Building a new Builder Xcessory executable
Once you create your Builder Xcessory interface file, you must rebuild the Builder Xcessory executable. An example makefile is available in {BX}/xcessory/examples/RebuildBX/Makefile.
The command line you use to recompile the Builder Xcessory executable varies from system to system. In general, use a command similar to the following:
- cc -o bx addWidget.o [objects] {BX}/lib/bx.o [libraries]
The example Makefile contains command lines for all of the platforms supported by Builder Xcessory 5.0
1
Some advanced Builder Xcessory users provide their own creation function for specific processing in addition to creating the widget, but name the usual ConvenienceFunction so that generated code is generated correctly.
2
The path assumes that the header file is installed with your other Motif header files.