Making the Widgets Available

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)

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

${HOME}/.builderXcessory/lib
{BX}/xcessory/lib
{BX}/lib
system shared-library search path

Note: On most systems, the shared-library search path is an environment variable such asLD_LIBRARY_PATH or SHLIB_PATH. Consult your system for details.


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:

#include <My/Widget.h>
Widget CreateMyDumbLabel(Widget parent, String name,
ArgList args, Cardinal ac)
{
return XtCreateWidget(name, xmDumbLabelWidgetClass,
parent, args, ac);
}

Compiling the creation function

To compile the creation function, use the following procedure:

  1. Use the correct position-independent code flag for your compiler.
  2. Create a shared library that contains this new object and is linked to the necessary widget library.
  3. Put this new intermediary library in one of the directories that Builder Xcessory searches.
  4. 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:

void AddUserWidgets()
void AddUserDefinedEditors()
void AddUserFunctions()

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_ptrAddress 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_nameName 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_ptrPointer 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_fileFile 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_prefixWidget 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.

void
AddUserWidgets()
{
}

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.

Documentation: